// Header.cpp: implementation of the CSIPHeader class.
//
//////////////////////////////////////////////////////////////////////
#pragma warning(disable:4530)

#include "osplatform.h"
#include "SIPHeader.h"

#ifdef _LINUX_
#include <strings.h>
#endif
#include <stdlib.h>
#include <assert.h>
#include <ctype.h>

#include "mystring.h"

#ifdef USE_DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif


int SkipLWS(const char *s,int len);
static char g_URIParamReserved[4] = {
	';','@','=',','
};
 
static char g_Reserved[10] = {
	';' ,
	'/' ,
	'?' ,
	':' ,
	'@' ,
	'&' ,
	'=' ,
	'+' ,
	'$' ,
	','
};
//alpha = 'a" - 'z'/'A'-'Z'
#ifdef IPV6_SUPPORT
bool is_ipv4_address(const char * p_address)
{
	int state = 0;
	int count = 0;
	char current_ch;
	int dot_count = 0;
	int digit_list_count = 0;
	if(!p_address)
		return false;
	while(*p_address != '\0')
	{
		/* begin ipv4 address parse*/
		current_ch = *p_address;
		p_address++;
		if(isdigit(current_ch))
		{
			if(!state)
				digit_list_count++;
			state = 1;count++;
			if(count > 3)
				return false;
			continue;
		}
		if(current_ch == '.')
		{
			if(state != 1)
				return false;
			state = 0;
			count = 0;		
			dot_count++;
			continue;
		}
		return false;
		/* end ipv4 address parse */
	}
	if(digit_list_count == 4 && dot_count == 3)
		return true;
	else
		return false;
}
bool ishexdig(int ch)
{
	int diff;
	diff = ch - '0';
	if(diff >= 0 && diff <= 9)
		return true;
	diff = ch - 'a';
	if(diff >= 0 && diff <= 'f'-'a')
		return true;
	diff = ch - 'A';
	if(diff >= 0 && diff <= 'F'- 'A')
		return true;
	return false;
}
bool is_ipv6_address(const char * p_address)
{
	int max_hex4_count = 8;
	int max_colon_count = 7;
	bool has_double_colon = false;
	int hex4_count = 0;
	int colon_count = 0;
	char current_ch;
	bool has_ipv4_address = false;
	int state = 0;
	int count = 0;
	if(!p_address)
		return false;
	while(*p_address != '\0')
	{
		current_ch = *p_address;
		p_address++;
		if(ishexdig(current_ch))
		{
			if(!state)
				hex4_count++;
			state = 1; count++;
			if(count > 4)
				return false;
			continue;
		}
		if(current_ch == ':')
		{
			if(*p_address != ':' && state == 0)
				return false;

			if(*p_address == ':')
			{
				if(has_double_colon)
					return false;
				has_double_colon = true;
				p_address++;
			}else
				colon_count++;
			state = 0; count = 0;
			if(is_ipv4_address(p_address))
			{
				has_ipv4_address = true;
				break;
			}
			continue;
		}
		return false;		
	}
	/* exceed count limit */
	if(hex4_count > max_hex4_count || colon_count > max_colon_count)
		return false;

	if(has_double_colon)
	{
		if( hex4_count == max_hex4_count || colon_count == max_colon_count)
			return false;
		return true;
	}
	if(has_ipv4_address)
	{/* has ipv4 address, hasn't double colon the colon and hex count should be 6*/
		if(hex4_count != 6 || colon_count != 6)
			return false;
		return true;
	}
    /* below condition: has no ipv4 address; has no double colon */
	if(hex4_count != max_hex4_count && colon_count != max_colon_count)
		return false;
	return true;
}
#endif
bool isALPHA(char ch)
{
	if((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z'))
		return true;
	return false;
}
//DIGIT = '0' - '9' %30 - 39
bool isDIGIT(char ch)
{
	if(ch >= '0' && ch <= '9')
		return true;
	return false;
}
//alphanum = ALPHA/DIGIT
bool isalphanum(char ch)
{
	if(isALPHA(ch) || isDIGIT(ch))
		return true;
	return false;
}

//reserved 
bool isreserved(char ch)
{
	for(int i=0;i<10;i++)
		if(g_Reserved[i] == ch)
			return true;
	return false;
}

//mark.
static char g_Mark[9] = {
	'-', '_', '.', '!', '~', '*', '\'', '(', ')'
};
bool ismark(char ch)
{
	for(int i=0;i<9;i++)
		if(g_Mark[i] == ch)
			return true;
	return false;
}

//unreserved = alphanum/mark
bool isunreserved(char ch)
{
	if(isalphanum(ch) || ismark(ch))
		return true;
	return false;
}

//token = 1*(alphanum / "-" / "." / "!" / "%" / "*"
//                     / "_" / "+" / "`" / "'" / "~" )
bool istoken(char ch)
{
#ifdef IPV6_SUPPORT
	static char token[] = {
		'-', '.', '!', '%', '*', '_', '+', '`', '\'', '~',':'
	};
#else
	static char token[10] = {
		'-', '.', '!', '%', '*', '_', '+', '`', '\'', '~'
	};
#endif
	if(isalphanum(ch))
		return true;
	for(int i=0;i<sizeof(token);i++)
		if(ch == token[i])
			return true;
	return false;
}

//separators  =  "(" / ")" / "<" / ">" / "@" /
//                     "," / ";" / ":" / "\" / DQUOTE /
//                     "/" / "[" / "]" / "?" / "=" /
//                     "{" / "}" / SP / HTAB

bool isseparators(char ch)
{
	
	static char separators[19]  = {
		'(' , ')' , '<' , '>' , '@' ,
        ',' , ';' , ':' , '\\' , DQUOTE ,
        ',' , '[' , ']' , '?' , '=' ,
        '{' , '}' , SP , HTAB};

	for(int i=0;i<19;i++)
	{
		if(ch == separators[i])
			return true;
	}
	return false;
}
//word        =  1*(alphanum / "-" / "." / "!" / "%" / "*" /
//                   "_" / "+" / "`" / "'" / "~" /
//                     "(" / ")" / "<" / ">" /
//                     ":" / "\" / DQUOTE /
//                     "/" / "[" / "]" / "?" /
//                     "{" / "}" )
bool isword(char ch)
{
	static char words[] = {
		'-' , '.' , '!' , '%' , '*' ,
        '_' , '+' , '`' , '\'' , '~' ,		 
		'(' , ')' , '<' , '>' ,	':' ,
		'\\' , DQUOTE ,',' , '[' , ']' ,
		'?' ,'{' , '}'
	};

	if(isalphanum(ch))
		return true;
	for(int i=0;i<23;i++)
	{
		if(ch == words[i])
			return true;
	}
	return false;
}
int ParseHost(const char *pbuf,int len,mystring &host)
{
	host.erase();
	const char *p = pbuf;
//const char *p1;
	int c1,c = 0;
	if(*p == '[')
	{//perhaps ipv6 address,find next ']';
		const char *p1 = p;
		c1 = c;
		while(*p1 != ']')
		{
			p1++;
			c1++;
			if(c1 >= len)
				return -1;
		}
		//now we got a ipv6 ,parse it
		//skip '['
		host += *p;
		p++;
		c++;
		while(*p != ']')
		{
			if(*p != ':' && (*p < '0' || *p > '9') && (*p < 'A' || *p > 'F') && (*p < 'a' || *p > 'f'))
			{
				return -1;
			}
			host += *p;
			p++;
			c++;
		}
		///skip ']'
		host += *p;
		p++;
		c++;
		return c;
	}
	while(*p != COLON)
	{
		if(*p == SP || *p == HTAB || *p == CR || *p == LF)
			break;
		if(isalphanum(*p) == false && *p != '-' && *p != '.')
			break;
		host += *p;
		p++;
		c++;
		if(c == len)
			return c;
	}
	return c;
}

int CSIPHeaderParams::ParseGenericParam(const char *pbuf,int len,mystring &v,bool &hasquote)
{
	const char *p = pbuf;
	int c1,c = 0;
	v.erase();
	hasquote = false;
	if(*p == DQUOTE)
	{//has "
	//  quoted-mystring  =  SWS DQUOTE *(qdtext / quoted-pair ) DQUOTE
	//qdtext         =  LWS / %x21 / %x23-5B / %x5D-7E
	//                    / UTF8-NONASCII
		//skip DQUOTE
		hasquote=true;
		p++;c++;
		while(*p != DQUOTE)
		{//skip LWS
			c1 = SkipLWS(p,len - c);
			if(c1 == -1)
				return -1;	
			p += c1;
			c += c1;	
			v += *p;
			p++;
			c++;
			if(c >= len)
				return -1;			
		}
		//skip DQUOTE
		p++;
		c++;
	}
	else
	{
#ifndef IPV6_SUPPORT
		if(*p == '[')
		{//perhaps ipv6 address,find next ']';
			const char *p1 = p;
			c1 = c;
			while(*p1 != ']')
			{
				p1++;
				c1++;
				if(c1 >= len)
					return -1;
			}
			//now we got a ipv6 ,parse it
			//skip '['
			p++;
			c++;
			while(*p != ']')
			{
				if(*p != ':' && (*p < '0' || *p > '9') && (*p < 'A' || *p > 'F'))
				{
					return -1;
				}
				v += *p;
				p++;
				c++;
			}
			///skip ']'
			p++;
			c++;
			return c;
		}
		while(*p != COLON)
#else
		if(is_ipv6_address(p))
		{
// just for test
		}
		while(1)
#endif
		{
			if(*p == SP || *p == HTAB || *p == CR || *p == LF)
				break;
			if(istoken(*p) == false)
				break;
			v += *p;
			p++;
			c++;
			if(c == len)
				return c;
		}
	}
	return c;
}
int ParseAsToken(const char *pbuf,int len,mystring &v)
{
	const char *p = pbuf;
	int c=0;
	v.erase();
	while(1)
	{
		if(istoken(*p) == false)
			break;
		v += *p;
		p++;c++;
		if(c >= len)
			return c;
	}
	return c;
}

int SkipLWS(const char *s,int len)
{
	const char *p = s;
	int c = 0;
again:
	
	while(*p == SP)
	{
		p++;
		c++;
		if(c == len)
			return c;
	}
	if(*p == CR && p[1] == LF)
	{
		if(p[2] == SP)
		{//it is LWS
			p+=2;
			c+=2;
			goto again;
		}
		
	}	
	//just skip space
	return c;	
}
int SkipAllWhiteSpace(const char *s,int len)
{
	const char *p = s;
	int c = 0;
	while(1)
	{
		if(*p == SP || *p == HTAB || *p == CR || *p == LF)
		{
			p++;
			c++;
			if(c >= len)
				break;
		}
		else
			break;
	}
	return c;
}
bool isEqualNoCase(const char *s1,const char *s2)
{
	if(s1 == NULL && s2 == NULL)
		return true;
	if(s1 == NULL || s2 == NULL)
		return false;
	if(mystricmp(s1,s2) == 0)
		return true;
	else
		return false;
}
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

int CSIPHeaderParams::ParseParams(const char *str,int len)
{
	if(str == NULL || len <= 0)
		return 0;
	const char *p = str;
	int c = 0;
	int c1;
	mystring name,value;
	while(*p != '=')
	{
		if(*p == SP || *p == HTAB || *p == CR || *p == LF || *p == SEMI)
			break;
		
		for(int i=0;i<sizeof(g_Reserved);i++)
		{
			if(*p == g_Reserved[i])
				goto out;
		}		
		name += *p;
		p++;
		c++;
		if(c == len)
			return c;		
	}
out:
	if(*p == EQUAL)
	{
		//skip '='
		p++;
		c++;
	}	
	else
	{
		c1 = SkipLWS(p,len - c);
		if(c1 == -1)
			return -1;
	
		p += c1;
		c += c1;
		if(*p == EQUAL)
		{//skip '='
			p++;
			c++;
		}
	}	
	c1 = SkipLWS(p,len - c);
	if(c1 == -1)
		return -1;	
	p += c1;
	c += c1;	
	//value 

	{
		while(*p != ';')
		{
			if(*p == SP || *p == HTAB || *p == CR || *p == LF)
				break;
			for(int i=0;i<sizeof(g_Reserved);i++)
			{
				if(*p == g_Reserved[i])
					goto out1;
			}
			value += *p;
			p++;
			c++;
			if(c == len)
				return c;
		}
	}
out1:
	AddParam(name.c_str(),value.c_str());
	return c;
}
int CSIPHeaderParams::ParseURIParams(const char *pbuf,int len)
{//uri-parameter = transport-param/user-param/method-param/ttl-param/maddr-param/lr-param/other-param
	const char *p = pbuf;
	int c = 0,c1;
	mystring name,value;
	int i;
	static char paramunreserved[7] = {'[',']','/',':','&','+','$'};
	while(*p != EQUAL)
	{
		if(*p == SP || *p == HTAB || *p == CR || *p == LF)
			break;
		
		if(isunreserved(*p) == false)
		{
			for(i=0;i<7;i++)
			{
				if(*p == paramunreserved[i])
					break;
			}
			if(i >= 7)
				break;
		}
		name += *p;
		p++;
		c++;
		if(c == len)
			return c;		
	}
	if(*p == EQUAL)
	{
		//skip '='
		p++;
		c++;
	}	
	else
	{
		c1 = SkipLWS(p,len - c);
		if(c1 == -1)
			return -1;
	
		p += c1;
		c += c1;
		if(*p == EQUAL)
		{//skip '='
			p++;
			c++;
		}
		else//no value
			return c;
	}	
	c1 = SkipLWS(p,len - c);
	if(c1 == -1)
		return -1;	
	p += c1;
	c += c1;	
	//value 
	if(mystricmp(name.c_str(),"transport") == 0 ||
		mystricmp(name.c_str(),"user") == 0 ||
		mystricmp(name.c_str(),"method") == 0 )
	{
		while(*p != ';')
		{
			if(istoken(*p) == false)
				break;
			value +=*p;
			p++;c++;
			if(c >= len)
				break;
		}
	}
	else if(mystricmp(name.c_str(),"ttl") == 0)
	{
		c1 = 0;
		while(1)
		{
			if(isDIGIT(*p) && c1 < 3)
			{
				value += *p;
				p++;
				c++;
				c1++;
				if(c >= len)
					break;
			}
			else
				break;
		}
	}
	else if(mystricmp(name.c_str(),"maddr") == 0)
	{
		c1 = ParseHost(p,len - c,value);
		
		p+=c1;
		c+=c1;
	}
	else
	{
		while(*p != ';')
		{
			if(*p == SP || *p == HTAB || *p == CR || *p == LF)
				break;

			if(isunreserved(*p) == false)
			{
				for(i=0;i<7;i++)
				{
					if(*p == paramunreserved[i])
						break;
				}
				if(i >= 7)
					break;
			}
			value += *p;
			p++;
			c++;
			if(c == len)
				return c;
		}
	}
	AddParam(name.c_str(),value.c_str());
	return c;
}
int CSIPHeaderParams::ParseVIAParams(const char *pbuf,int len)
{//via-params=via-ttl/via-maddr/via-received/via-branch/via-externsion
	const char *p = pbuf;
	int c = 0,c1;
	bool hasquote=false;
	mystring name,value;
	while(*p != '=')
	{
		if(*p == SP || *p == HTAB || *p == CR || *p == LF || *p == SEMI || *p == COMMA)
			break;
		if(istoken(*p) == false)
			break;
		name += *p;
		p++;
		c++;
		if(c == len)
			return c;		
	}
	SKIPLWS(p,len,c,c1);

	if(*p == EQUAL)
	{
		//skip '='
		p++;
		c++;
	}	
	else
	{
		c1 = SkipLWS(p,len - c);
		if(c1 == -1)
			return -1;
	
		p += c1;
		c += c1;
		if(*p == EQUAL)
		{//skip '='
			p++;
			c++;
		}
		else
			return c;
	}	
	c1 = SkipLWS(p,len - c);
	if(c1 == -1)
		return -1;	
	p += c1;
	c += c1;	
	//skip SWS
	c1 = SkipLWS(p,len - c);
	if(c1 == -1)
		return -1;	
	p += c1;
	c += c1;	
	//value
	if(mystricmp(name.c_str(),"ttl") == 0)
	{
		c1 = 0;
		while(1)
		{
			if(isDIGIT(*p) && c1 < 3)
			{
				value += *p;
				p++;
				c++;
				c1++;
				if(c >= len)
					break;
			}
			else
				break;
		}
	}
	else if(mystricmp(name.c_str(),"maddr") == 0)
	{
		c1 = ParseHost(p,len - c,value);
		
		p+=c1;
		c+=c1;
	}
	else
	{
		c1 = ParseGenericParam(p,len - c,value,hasquote);
		p+=c1;
		c+=c1;
	}

	AddParam(name.c_str(),value.c_str(),hasquote);
	return c;	
}

mystring CSIPHeaderParams::Encode()
{
	mystring en;
	en = "";
	const ParamPair *par;
	SeekHead();
	while((par = GetNext()))
	{
		en +=";";
		en += par->m_pName;
		if(par->m_pValue && strlen(par->m_pValue) > 0)
		{
			en += "=";
			if(par->m_bHasQuote)
			{
				en +="\"";
				en += par->m_pValue;
				en +="\"";
			}
			else
				en += par->m_pValue;
		}
	}
	return en;
}
mystring CSIPHeaderParams::EncodeHeaders()
{
	mystring en;
	en = "";
	const ParamPair *par;
	SeekHead();
	int c = 0;
	while((par = GetNext()))
	{
		if(c == 0)
			en +="?";
		else
			en += "&";
		c++;
		en += par->m_pName;
		if(par->m_pValue && strlen(par->m_pValue) > 0)
		{
			en += "=";
			en += par->m_pValue;
		}
	}
	return en;
}
void CSIPHeaderParams::Clear()
{	
	struct ParamPair *del;
	while(m_pHead)
	{		
		del = m_pHead;
		m_pHead = m_pHead->m_pNext;
		delete del;
	}
	m_pCur = m_pHead = m_pTail = NULL;
	m_nSize = 0;
}

bool CSIPHeaderParams::AddParam(const char *pname,const char *pvalue,bool hasquote)
{
	assert(pname);
	if(strlen(pname) == 0)
		return false;
	//assert(pvalue);
	struct ParamPair *pi = new struct ParamPair;
	pi->m_pNext = NULL;
	pi->m_pName = new char[strlen(pname)+1];
	strcpy(pi->m_pName,pname);
	pi->m_bHasQuote = hasquote;
	if(pvalue && strlen(pvalue) > 0)
	{
		pi->m_pValue = new char[strlen(pvalue)+1];
		strcpy(pi->m_pValue,pvalue);
	}
	if(m_pHead)
	{
		m_pTail->m_pNext = pi;
		m_pTail = pi;
	}
	else
	{
		m_pHead = pi;
		m_pCur = m_pHead;
		m_pTail = pi;
	}
	m_nSize++;
	return true;
}
bool CSIPHeaderParams::SetValue(const char *pname,const char *pvalue)
{
	assert(pname);
	struct ParamPair *pi = m_pHead;
	while(pi)
	{
		if(mystricmp(pname,pi->m_pName) == 0)
		{
			if(pi->m_pValue)
			{
				delete[] pi->m_pValue;
				if(pvalue && strlen(pvalue)>0)
				{
					pi->m_pValue = new char[strlen(pvalue)+1];
					strcpy(pi->m_pValue,pvalue);
				}
				else
					pi->m_pValue = NULL;
			}
			else
			{
				if(pvalue && strlen(pvalue) > 0)
				{
					pi->m_pValue = new char[strlen(pvalue)+1];
					strcpy(pi->m_pValue,pvalue);
				}
			}
			return true;
		}
		pi = pi->m_pNext;
	}
	return AddParam(pname,pvalue);
}
const char *CSIPHeaderParams::GetValue(const char *pname)const
{
	struct ParamPair *pi = m_pHead;
	while(pi)
	{
		if(mystricmp(pname,pi->m_pName) == 0)
			return pi->m_pValue;
		pi = pi->m_pNext;
	}
	return NULL;
}
bool CSIPHeaderParams::FindName(const char *pname)const
{
	struct ParamPair *pi = m_pHead;
	while(pi)
	{
		if(mystricmp(pname,pi->m_pName) == 0)
			return true;
		pi = pi->m_pNext;
	}
	return false;
}
/*
bool CSIPHeaderParams::GetValue(const char *pname)const
{
	struct ParamPair *pi = m_pHead;
	while(pi)
	{
		if(mystricmp(pname,pi->m_pName) == 0)
			return true;
		pi = pi->pnext;
	}
	return false;
}
*/
const ParamPair* CSIPHeaderParams::GetNext()
{
	ParamPair *p = NULL;
	if(m_pCur)
	{
		p = m_pCur;
		m_pCur = m_pCur->m_pNext;
	}
	return p;
}
void CSIPHeaderParams::SeekHead()
{
	m_pCur = m_pHead;
}
CSIPHeaderParams& CSIPHeaderParams::operator=(const CSIPHeaderParams& rhs)
{
	if(this != &rhs)
	{
		Clear();
		ParamPair *p = rhs.m_pHead;
		while(p)
		{
			AddParam(p->m_pName,p->m_pValue,p->m_bHasQuote);
			p = p->m_pNext;
		}
	}
	return *this;
}

bool CSIPHeaderParams::operator==(const CSIPHeaderParams& other) const
{
	ParamPair *p;
	const char *pvalue;
	p = other.m_pHead;
	if(GetSize() != other.GetSize())
		return false;
	while(p)
	{
		pvalue = this->GetValue(p->m_pName);
		if(pvalue == NULL && p->m_pValue)
			return false;
		if(pvalue)
		{
			if(strcmp(pvalue,p->m_pValue))
				return false;
		}
		p = p->m_pNext;
	}
	return true;
}

bool CSIPHeaderParams::operator!=(const CSIPHeaderParams& other) const
{
   return !(*this == other);
}


char CSIPHeader::m_sHeaderNames[MAX_HEADERS][32] = {
		"Content-Disposition", 
		"Content-Encoding",
		"Content-Transfer-Encoding", 
		"Mime-Version",
		"Priority",
		"Event",
		"Allow-Events",		
		"Accept-Encoding",
		"Accept-Language", 
		"Allow",
		"Content-Language",
		"Proxy-Require", 
		"Require", 
		"Supported", 
		"Subscription-State",
		"Unsupported",
		"Security-Client",
		"Security-Server", 
		"Security-Verify",
		//====================
		// Mime
		//====================
		"Accept",
		"Content-Type",
		//====================
		// GenericURIs:
		//====================
		"Call-Info", 
		"Alert-Info",
		"Error-Info",
		//====================
		// NameAddr:
		//====================
		"Record-Route", 
		"Route",
		"Contact", 
		 "From",
		"To", 
		"Reply-To",
		"Refer-To", 
		"Referred-By",
		//====================
		// String:
		//====================
		"Organization",
		"Server",
		"Subject",
		"User-Agent",
		 "Timestamp",
		//====================
		// Integer:
		//====================		
		"Content-Length", 
		"Max-Forwards",
		"Min-Expires",	
		"Retry-After",
		"Expires",
		//====================
		// CallId:
		//====================
		"Call-ID",
		"Replaces", 
		"In-Reply-To",
		//====================
		// Auth:
		//====================	
		"Authentication-Info",
		"Authorization",
		"Proxy-Authenticate", 
		"Proxy-Authorization",
		"Www-Authenticate",	
		"CSeq",	
		"Date", 	
		"Warning",	
		"Via",
		"Translate",
		"Scale",
		"Seek",
};

CSIPHeader::CSIPHeader()
{
	m_eType = UNKNOWN;
}

CSIPHeader::~CSIPHeader()
{

}

void CSIPHeader::AddParam(const char *pname,const char *pvalue,bool hasquote)
{
	m_Params.AddParam(pname,pvalue,hasquote);
}
bool CSIPHeader::SetValue(const char *pname,const char *pvalue)
{
	return m_Params.SetValue(pname,pvalue);
}
const char *CSIPHeader::GetValue(const char *pname)const
{
	return m_Params.GetValue(pname);
}
bool CSIPHeader::FindParam(const char *pname)const
{
	return m_Params.FindName(pname);
}
/*
bool CSIPHeader::GetValue(const char *pname)const
{
	return m_Params.GetValue(pname);
}
*/
CSIPUri::CSIPUri()
{
//	m_strScheme.erase();
//	m_strHost.erase();
//	m_strUser.erase();
//	m_strPassword.erase();
	m_nPort = 0;
}
CSIPUri::CSIPUri(const CSIPUri &uri)
{
	*this = uri;
}
CSIPUri::~CSIPUri()
{
	Clear();
}

void CSIPUri::Clear()
{
	m_strScheme.erase();
	
	m_strHost.erase();
	m_strUser.erase();
	m_strPassword.erase();
	m_Params.Clear();
	m_nPort =0;
}
mystring CSIPUri::AddressOfRecord()const
{
	mystring en;
	en = m_strScheme;
	en +=":";
	if(m_strUser.empty() == false)
	{
		en += m_strUser;
		en += "@";
	}
	if(m_strHost.empty() == false)
		en += m_strHost;
	return en;
}
mystring CSIPUri::AddressOfRecordNoScheme()const
{
	mystring en;
	if(m_strUser.empty() == false)
	{
		en = m_strUser;
		en += "@";
	}
	if(m_strHost.empty() == false)
		en += m_strHost;
	return en;
}
mystring CSIPUri::Encode()
{
	mystring en;
	if(m_strScheme.empty() == false)
		en = m_strScheme;
	else
		en = "sip";	
	en += ":";
	if(m_strUser.empty() == false)
	{
		en += m_strUser;
		if(m_strPassword.empty() == false)
		{
			en +=":";
			en +=m_strPassword;
		}
		en += "@";
	}
#ifdef IPV6_SUPPORT
	if(is_ipv6_address(m_strHost.c_str()))
	{
		en += "[";
		en += m_strHost;
		en += "]";
	}else
		en += m_strHost;
#else
		en += m_strHost;
#endif
	if(m_nPort > 0)
	{
		char buf[24];
		sprintf(buf,"%d",m_nPort);
		en +=":";
		en += buf;
	}
	en += m_Params.Encode();
	en += m_Headers.EncodeHeaders();
	return en;
}
CSIPUri& CSIPUri::operator=(const CSIPUri& rhs)
{   
	if (this != &rhs)
	{  		
		m_strScheme = rhs.m_strScheme;
		m_strHost = rhs.m_strHost;
		m_strUser = rhs.m_strUser;
		m_strPassword = rhs.m_strPassword;		  
		m_nPort = rhs.m_nPort;
		m_Params = rhs.m_Params;
	}
	return *this;
}
bool CSIPUri::operator==(const CSIPUri& other) const
{
	if(m_strScheme.empty() == false || other.m_strScheme.empty() == false)
	{
		if(isEqualNoCase(m_strScheme.c_str(),other.m_strScheme.c_str()) == false)
			return false;
	}
	if(m_strUser != other.m_strUser)
		return false;
	if(m_strPassword != other.m_strPassword)
		return false;

	if(isEqualNoCase(m_strHost.c_str(), other.m_strHost.c_str()) == false)
		return false;
	
	if(m_nPort != other.m_nPort)
		return false;

	const char* b1,*b2;
	if((b1 = m_Params.GetValue("Transport")) || (b2 = other.m_Params.GetValue("Transport")))
	{
		if(b1 == NULL || b2 == NULL)
			return false;
		if(isEqualNoCase(m_Params.GetValue("Transport"),other.m_Params.GetValue("Transport")) == false)
			return false;
	}
    if((b1 = m_Params.GetValue("security")) && (b2 = other.m_Params.GetValue("security")))
	{	
		if(isEqualNoCase(b1,b2) == false)
			return false;
	}
	return true;
}

bool CSIPUri::operator!=(const CSIPUri& other) const
{
   return !(*this == other);
}

bool CSIPUri::operator<(const CSIPUri& other) const
{
   return m_nPort < other.m_nPort;
}
void CSIPUri::SetScheme(const char *pscheme)
{		
	m_strScheme = pscheme;
}
void CSIPUri::SetHost(const char *phost)
{	
	m_strHost = phost;
}
void CSIPUri::SetUser(const char *puser)
{	
	m_strUser = puser;
}
void CSIPUri::SetPassword(const char *ppassword)
{	
	m_strPassword = ppassword;
}
int CSIPUri::ParseNetPath(const char *pbuf,int len)
{
	return 0;
}
int CSIPUri::ParseABSPath(const char *pbuf,int len)
{
	return 0;
}

int CSIPUri::Parse(const char *puri,int len,bool param)
{//SIP-URI/SIPS-URI
//SIP-RUI="sip:" [userinfo] hostport uri-parameters [headers]
	Clear();
	if(puri == NULL || len <= 0)
		return -1;
	const char *p = puri;
	int c = 0,c1;
	
	while(*p != COLON)
	{
		if(*p == SP || *p == HTAB || *p == CR || *p == LF)
			return -1;
		for(int i=0;i<sizeof(g_Reserved);i++)
		{
			if(*p == g_Reserved[i] && *p != '+')
			{
				return -1;
			}
		}
		m_strScheme += *p;
		p++;
		c++;
		if(c >= len)
			return -1;

	}
	p++;//skip COLON
	c++;
	if(mystricmp(m_strScheme.c_str(),"sip") == 0 ||
		mystricmp(m_strScheme.c_str(),"sips") == 0)
	{
		c1 = ParseSIP(p,len - c,param);
		if(c1 == -1)
			return -1;
		c+=c1;
		p+=c1;
		return c;
	}
	else if(mystricmp(m_strScheme.c_str(),"tel") == 0)
	{//tel
		return -1;
	}
	if(*p == '/' && p[1] == '/')
	{//net-path
	//skip //
		p+=2;
		c+=2;
		if(c >= len)
			return -1;
		//authority = srvr/reg-name
		//srvr = [[userinfo "@"] hostport]
		return -1;
	}
	else if(*p == '/')
	{//abs-path
		return -1;
	}
	else
	{//opaque-path
		return -1;
	}
}
int CSIPUri::ParseSIP(const char *pbuf,int len,bool param)
{
	const char *p = pbuf;
	int c = 0,c1;
	const char *p1 = p;
	c1 = c;
	//find "@"
	while(*p1 != '@')
	{
		if(*p1 == CR || *p1 == LF || *p1 == SP)
			break;
		p1++;
		c1++;
		if(c1 >= len)
			break;

	}
	if(*p1 == '@')
	{//find userinfo
		while(*p != COLON && *p != '@')
		{
			m_strUser += *p;
			p++;
			c++;
		}
		if(*p == COLON)
		{//has password
			p++;//skip COLON
			c++;
			while(*p != '@')
			{
				m_strPassword += *p;
				p++;
				c++;
			}
		}
	}
	if(*p == '@')
	{//skip
		p++;
		c++;
	}
	//host:port
	c1 = ParseHost(p,len - c,m_strHost);
	if(c1 == -1)
		return -1;
	p+=c1;
	c+=c1;
	if(*p == COLON)
	{//have port, skip COLON 
		p++;
		c++;
		mystring port;
		while(*p != ';')
		{
			if(*p == SP || *p == HTAB || *p == CR || *p == LF)
				break;
			port += *p;
			p++;
			c++;
			if(c == len)
				break;
		}
		m_nPort = atoi(port.c_str());
		if(c == len)
			return c;
		if(c > len)
			return -1;
	}
	if(param == false)
		return c;
	while(*p == ';')
	{//has uri-parameter,skip ';'
		p++;c++;
		c1 = m_Params.ParseParams(p,len - c);
		if(c1 == -1)
			return -1;
		p += c1;
		c+=c1;
	}
	if(*p == '?')
	{//has headers = "?" header *("&" header)		
		p++;c++;
		c1 = m_Headers.ParseParams(p,len - c);
		if(c1 == -1)
			return -1;
		p+=c1;
		c+=c1;
		while(*p == '&')
		{
			p++;c++;
			c1 = m_Headers.ParseParams(p,len - c);
			if(c1 == -1)			
				return -1;
			p+=c1;
			c+=c1;
		}
	}
	return c;
}

CSIPAbsoluteUri::CSIPAbsoluteUri()
{
//	m_strScheme.erase();
//	m_strHost.erase();
////	m_strUser.erase();
//	m_strPassword.erase();	
//	m_strQuery.erase();
//	m_strRegName.erase();
//	m_strOpaquePath.erase();
	m_nPort = 0;
}
CSIPAbsoluteUri::CSIPAbsoluteUri(const CSIPAbsoluteUri &uri)
{
	*this = uri;
}
CSIPAbsoluteUri::~CSIPAbsoluteUri()
{
	Clear();
}

void CSIPAbsoluteUri::Clear()
{
	m_strScheme.erase();	
	m_strHost.erase();
	m_strUser.erase();
	m_strPassword.erase();	
	m_strOpaquePath.erase();
	m_nPort =0;
	while(m_Segments.empty() == false)
	{
		m_Segments.pop_front();
	}
}
mystring CSIPAbsoluteUri::Encode()
{
	mystring en;
	if(m_strScheme.empty() == false)
		en = m_strScheme;
	else
		en = "sip:";	
	if(m_strUser.empty() == false)
	{
		en += m_strUser;
		if(m_strPassword.empty() == false)
		{
			en +=":";
			en +=m_strPassword;
		}
		en += "@";
	}
	en += m_strHost;
	if(m_nPort > 0)
	{
		char buf[24];
		sprintf(buf,"%d",m_nPort);
		en +=":";
		en += buf;
	}
	
	return en;
}
CSIPAbsoluteUri& CSIPAbsoluteUri::operator=(const CSIPAbsoluteUri& rhs)
{
   
	if (this != &rhs)
	{  		
		m_strScheme = rhs.m_strScheme;
		m_strHost = rhs.m_strHost;
		m_strUser = rhs.m_strUser;
		m_strPassword = rhs.m_strPassword;		  
		m_strQuery = rhs.m_strQuery;
		m_strRegName = rhs.m_strRegName;
		m_strOpaquePath = rhs.m_strOpaquePath;
		m_nPort = rhs.m_nPort;
				
		
	}
	return *this;
}

int CSIPAbsoluteUri::Parse(const char *pbody,int len)
{//SIP-URI/SIPS-URI
//SIP-RUI="sip:" [userinfo] hostport uri-parameters [headers]
	Clear();
	if(pbody == NULL || len <= 0)
		return -1;
	const char *p = pbody;
	int c = 0;	
	while(*p != COLON)
	{
		if(*p == SP || *p == HTAB || *p == CR || *p == LF)
			return -1;
		for(int i=0;i<sizeof(g_Reserved);i++)
		{
			if(*p == g_Reserved[i] && *p != '+')
			{
				return -1;
			}
		}
		m_strScheme += *p;
		p++;
		c++;
		//if(c >= len) // Modified by liuhf 2007.10.9
		//	return -1
		if(c == len)
			return c;
	}

	// added by liuhf 2007.10.9

	p++;//skip COLON
	c++;
	if(*p == '/' && p[1] == '/')
	{//net-path
	//skip //
		p+=2;
		c+=2;
		if(c >= len)
			return -1;
		//authority = srvr/reg-name
		//srvr = [[userinfo "@"] hostport]
		
	}
	else if(*p == '/')
	{//abs-path
	}
	else
	{//opaque-path
	}
	return c;
}

CSIPCallID::CSIPCallID(const CSIPCallID &cid)
{
	*this = cid;
}
void CSIPCallID::Clear()
{
	m_strCallID.erase();
}
mystring CSIPCallID::Encode()
{
	mystring en;
	en = "Call-ID: ";
	en += m_strCallID;
	return en;
}
mystring CSIPCallID::EncodeNoName()
{
	mystring en;
	en = m_strCallID;
	return en;
}
CSIPCallID& CSIPCallID::operator=(const CSIPCallID& rhs)
{
   
	if (this != &rhs)
	{  
		m_strCallID = rhs.m_strCallID;	
	}
	return *this;
}
bool CSIPCallID::operator==(const CSIPCallID& other) const
{
   if (isEqualNoCase(m_strCallID.c_str(), other.m_strCallID.c_str()))      
   {
        return true;      
   }
   else
   {
      return false;
   }   
   return true;
}

bool CSIPCallID::operator!=(const CSIPCallID& other) const
{
   return !(*this == other);
}

bool CSIPCallID::operator<(const CSIPCallID& other) const
{
	/*
	if(m_pCallID == NULL || other.m_pCallID == NULL)
		return false;
	if (mystricmp(m_pCallID,other.m_pCallID) < 0)
	{
		return true;
	}
	*/
	return false;
}
void CSIPCallID::SetCallId(const char *pcallid)
{
	m_strCallID = pcallid;
}
int CSIPCallID::Parse(const char *pbody,int len)
{
	if(pbody == NULL || len <= 0)
		return 0;
	const char *p = pbody;
	int c = 0;
	while(*p != CR)
	{
		if(*p == SP || *p == HTAB || *p == CR || *p == LF)
			break;
		m_strCallID += *p;
		p++;
		c++;
		if(c >= len)
			return c;
	}
	return c;
}


CSIPTo::CSIPTo():m_NameAddr()
{
}
CSIPTo::CSIPTo(const CSIPTo &addr)
{	
	*this = addr;
}
CSIPTo::~CSIPTo()
{
	Clear();
}
void CSIPTo::SetDisplayName(const char *pname)
{	
	m_NameAddr.SetDisplayName(pname);
}


void CSIPTo::Clear()
{
	m_NameAddr.Clear();
}

int CSIPTo::Parse(const char *pbody,int len)
{//name-addr = [display-name]LAQUOT addr-spec RAQUOT
//addr-spec = SIP-URI/SIPS-URI/absoluteRUI
//display-name = *(token LWS)/quoted-mystring
	Clear();
	int c = 0,c1;
	const char *p = pbody;
	c = m_NameAddr.Parse(p,len);
	if(c == -1)
		return -1;
	p+=c;
	SKIPLWS(p,len,c,c1);
	while(*p == SEMI)
	{
		p++;c++;
		SKIPLWS(p,len,c,c1);
		c1 = m_Params.ParseURIParams(p,len - c);
		if(c1 == -1)
			return -1;
		p+=c1;
		c+=c1;
		SKIPLWS(p,len,c,c1);
	}
	return c;
}
mystring CSIPTo::Encode()
{
	mystring en;
	en = "To: ";
	en += m_NameAddr.Encode();
	en += m_Params.Encode();
	return en;
}
mystring CSIPTo::EncodeNoName()
{
	mystring en;
	en = m_NameAddr.Encode();
	en += m_Params.Encode();
	return en;
}
CSIPTo& CSIPTo::operator=(const CSIPTo& rhs)
{   
	m_NameAddr = rhs.m_NameAddr;
	m_Params = rhs.m_Params;
	return *this;
}
bool CSIPTo::operator==(const CSIPTo& other) const
{   
   if(m_NameAddr != other.m_NameAddr)
	   return false;
   
   return true;
}

bool CSIPTo::operator!=(const CSIPTo& other) const
{
   return !(*this == other);
}


CSIPFrom::CSIPFrom():m_NameAddr()
{
}
CSIPFrom::CSIPFrom(const CSIPFrom &addr)
{	
	*this = addr;
}
CSIPFrom::~CSIPFrom()
{
	Clear();
}
void CSIPFrom::SetDisplayName(const char *pname)
{	
	m_NameAddr.SetDisplayName(pname);
}


void CSIPFrom::Clear()
{
	m_NameAddr.Clear();
}

int CSIPFrom::Parse(const char *pbody,int len)
{//name-addr = [display-name]LAQUOT addr-spec RAQUOT
//addr-spec = SIP-URI/SIPS-URI/absoluteRUI
//display-name = *(token LWS)/quoted-mystring
	Clear();
	int c = 0;
	int c1;
	const char *p = pbody;
	c = m_NameAddr.Parse(p,len);
	if(c == -1)
		return -1;
	p+=c;
	SKIPLWS(p,len,c,c1);
	while(*p == SEMI)
	{
		p++;c++;
		SKIPLWS(p,len,c,c1);
		c1 = m_Params.ParseURIParams(p,len - c);
		if(c1 == -1)
			return -1;
		p+=c1;
		c+=c1;
		SKIPLWS(p,len,c,c1);
	}
	return c;
}
mystring CSIPFrom::Encode()
{
	mystring en;
	en = "From: ";
	en += m_NameAddr.Encode();
	en += m_Params.Encode();
	return en;
}
mystring CSIPFrom::EncodeNoName()
{
	mystring en;
	en = m_NameAddr.Encode();
	en += m_Params.Encode();
	return en;
}

CSIPFrom& CSIPFrom::operator=(const CSIPFrom& rhs)
{   
	m_NameAddr = rhs.m_NameAddr;
	m_Params = rhs.m_Params;
	return *this;
}
bool CSIPFrom::operator==(const CSIPFrom& other) const
{   
   if(m_NameAddr != other.m_NameAddr)
	   return false;
   
   return true;
}

bool CSIPFrom::operator!=(const CSIPFrom& other) const
{
   return !(*this == other);
}


CSIPProxyAuthenticate::CSIPProxyAuthenticate()
{
	
}

CSIPProxyAuthenticate::CSIPProxyAuthenticate(const CSIPProxyAuthenticate &e)
{
	*this = e;
}
CSIPProxyAuthenticate::~CSIPProxyAuthenticate()
{
	Clear();
}
int CSIPProxyAuthenticate::Parse(const char *pbody,int len)
{
	const char *p = pbody;
	int c1 ,c = 0;	
	mystring digest;
	mystring name,value;
	Clear();
	while(1)
	{
		if(*p == SP || *p == HTAB || *p == CR || *p == LF)
			break;
				
		digest += *p;
		p++;c++;
		if(c >= len)
			return -1;
	}	
	SKIPLWS(p,len,c,c1);

	while(1)
	{
		name.erase();
		value.erase();
		SKIPLWS(p,len,c,c1);
		while(*p != '=')
		{
			if(*p == SP || *p == HTAB || *p == CR || *p == LF)
				break;				
			name += *p;
			p++;c++;
			if(c >= len)
				return -1;
		}		
		SKIPLWS(p,len,c,c1);
		if(*p != '=')
			return -1;

		p++;
		c++;
		SKIPLWS(p,len,c,c1);		
		if(*p != DQUOTE)
			return -1;
		p++;
		c++;
		SKIPLWS(p,len,c,c1);
		while(*p != DQUOTE)
		{			
			value += *p;
			p++;c++;
			if(c >= len)
				return -1;
		}
		SKIPLWS(p,len,c,c1);
		p++;
		c++;
		SKIPLWS(p,len,c,c1);
		if(name == "domain")
			m_strDomain = value;
		else if(name == "opaque")
			m_strOpaque = value;
		else if(name == "qop")
			m_strQop = value;
		else if(name == "nonce")
			m_strNonce = value;
		else if(name == "stale")
			m_strStale = value;
		else if(name == "algorithm")
			m_strAlgorithm = value;
		else if(name == "realm")
			m_strRealm = value;
		else
		{
			m_strAuthParamName = name;
			m_strAuthParam = value;
		}
		if(*p != COMMA)
			break;
		p++;
		c++;
	}
	return c;	
}
mystring CSIPProxyAuthenticate::Encode()
{
	mystring en;
	bool comma = false;
	en = "Proxy-Authenticate: Digest ";
	if(m_strRealm.empty() == false)
	{
		en += "realm='\"" + m_strRealm + "\"";
		comma = true;
	}
	if(m_strDomain.empty() == false)
	{
		if(comma)
			en += ",domain=\"" + m_strDomain + "\"";
		else
		{
			en += "dommain=\"" + m_strDomain + "\"";
			comma = true;
		}
	}
	if(m_strQop.empty() == false)
	{
		if(comma)
			en += ",qop=\"" + m_strQop + "\"";
		else
		{
			en += "qop=\"" + m_strQop + "\"";
			comma = true;
		}
	}
	if(m_strNonce.empty() == false)
	{
		if(comma)
			en += ",nonce=\"" + m_strNonce + "\"";
		else
		{
			en += "nonce=\"" + m_strNonce + "\"";
			comma = true;
		}
	}
	if(m_strAlgorithm.empty() == false)
	{
		if(comma)
			en += ",algorithm=\"" + m_strAlgorithm + "\"";
		else
		{
			en += "nonce=\"" + m_strAlgorithm + "\"";
			comma = true;
		}
	}
	if(m_strOpaque.empty() == false)
	{
		if(comma)
			en += ",opaque=\"" + m_strOpaque + "\"";
		else
		{
			en += "opaque=\"" + m_strOpaque + "\"";
			comma = true;
		}
	}
	if(m_strStale.empty() == false)
	{
		if(comma)
			en += ",stale=\"" + m_strStale + "\"";
		else
		{
			en += "stale=\"" + m_strStale + "\"";
			comma = true;
		}
	}
	if(m_strAuthParam.empty() == false)
	{
		if(comma)
			en += "," + m_strAuthParamName + "=\"" + m_strStale + "\"";
		else
		{
			en += m_strAuthParamName + "=\"" + m_strStale + "\"";
			comma = true;
		}
	}
	return en;
}

mystring CSIPProxyAuthenticate::EncodeNoName()
{
	mystring en;
	bool comma = false;
	en = "Digest ";
	if(m_strRealm.empty() == false)
	{
		en += "realm='\"" + m_strRealm + "\"";
		comma = true;
	}
	if(m_strDomain.empty() == false)
	{
		if(comma)
			en += ",domain=\"" + m_strDomain + "\"";
		else
		{
			en += "dommain=\"" + m_strDomain + "\"";
			comma = true;
		}
	}
	if(m_strQop.empty() == false)
	{
		if(comma)
			en += ",qop=\"" + m_strQop + "\"";
		else
		{
			en += "qop=\"" + m_strQop + "\"";
			comma = true;
		}
	}
	if(m_strNonce.empty() == false)
	{
		if(comma)
			en += ",nonce=\"" + m_strNonce + "\"";
		else
		{
			en += "nonce=\"" + m_strNonce + "\"";
			comma = true;
		}
	}
	if(m_strAlgorithm.empty() == false)
	{
		if(comma)
			en += ",algorithm=\"" + m_strAlgorithm + "\"";
		else
		{
			en += "nonce=\"" + m_strAlgorithm + "\"";
			comma = true;
		}
	}
	if(m_strOpaque.empty() == false)
	{
		if(comma)
			en += ",opaque=\"" + m_strOpaque + "\"";
		else
		{
			en += "opaque=\"" + m_strOpaque + "\"";
			comma = true;
		}
	}
	if(m_strStale.empty() == false)
	{
		if(comma)
			en += ",stale=\"" + m_strStale + "\"";
		else
		{
			en += "stale=\"" + m_strStale + "\"";
			comma = true;
		}
	}
	if(m_strAuthParam.empty() == false)
	{
		if(comma)
			en += "," + m_strAuthParamName + "=\"" + m_strStale + "\"";
		else
		{
			en += m_strAuthParamName + "=\"" + m_strStale + "\"";
			comma = true;
		}
	}
	return en;
}

CSIPProxyAuthenticate& CSIPProxyAuthenticate::operator=(const CSIPProxyAuthenticate& rhs)
{
	Clear();
	m_strDomain = rhs.m_strDomain;
	m_strAlgorithm = rhs.m_strAlgorithm;
	m_strQop = rhs.m_strQop;
	m_strNonce = rhs.m_strNonce;
	m_strRealm = rhs.m_strRealm;
	m_strStale = rhs.m_strStale;
	m_strOpaque = rhs.m_strOpaque;
	m_strAuthParam = rhs.m_strAuthParam;
	m_strAuthParamName = rhs.m_strAuthParamName;
	return *this;
}
bool CSIPProxyAuthenticate::operator==(const CSIPProxyAuthenticate& other) const
{	
	if(m_strDomain != other.m_strDomain)
		return false;
	if(m_strAlgorithm != other.m_strAlgorithm)
		return false;
	if(m_strQop != other.m_strQop)
		return false;
	if(m_strNonce != other.m_strNonce)
		return false;
	if(m_strRealm != other.m_strRealm)
		return false;
	if(m_strStale != other.m_strStale)
		return false;
	if(m_strOpaque != other.m_strOpaque)
		return false;
	if(m_strAuthParam != other.m_strAuthParam)
		return false;
	if(m_strAuthParamName != other.m_strAuthParamName)
		return false;
	return true;
}
bool CSIPProxyAuthenticate::operator!=(const CSIPProxyAuthenticate& other) const
{
	return !(*this == other);
}
void CSIPProxyAuthenticate::Clear()
{	
	m_strDomain.erase();
	m_strAlgorithm.erase();
	m_strQop.erase();
	m_strNonce.erase();
	m_strRealm.erase();
	m_strStale.erase();
	m_strOpaque.erase();
	m_strAuthParam.erase();
	m_strAuthParamName.erase();
}




CSIPProxyAuthorization::CSIPProxyAuthorization()
{
	
}

CSIPProxyAuthorization::CSIPProxyAuthorization(const CSIPProxyAuthorization &e)
{
	*this = e;
}
CSIPProxyAuthorization::~CSIPProxyAuthorization()
{
	Clear();
}
int CSIPProxyAuthorization::Parse(const char *pbody,int len)
{
	const char *p = pbody;
	int c1 ,c = 0;	
	mystring digest;
	mystring name,value;
	Clear();
	while(*p != COMMA)
	{
		if(*p == SP || *p == HTAB || *p == CR || *p == LF)
			break;
				
		digest += *p;
		p++;c++;
		if(c >= len)
			return -1;
	}	
	SKIPLWS(p,len,c,c1);

	while(1)
	{
		name.erase();
		value.erase();		
		SKIPLWS(p,len,c,c1);
		while(*p != '=')
		{
			if(*p == SP || *p == HTAB || *p == CR || *p == LF)
				break;				
			name += *p;
			p++;c++;
			if(c >= len)
				return -1;
		}		
		SKIPLWS(p,len,c,c1);
		if(*p != '=')
			return -1;

		p++;
		c++;
		SKIPLWS(p,len,c,c1);		
		if(*p != DQUOTE)
			return -1;
		p++;
		c++;
		SKIPLWS(p,len,c,c1);
		while(*p != DQUOTE)
		{			
			value += *p;
			p++;c++;
			if(c >= len)
				return -1;
		}
		SKIPLWS(p,len,c,c1);
		p++;
		c++;
		SKIPLWS(p,len,c,c1);
		if(name == "username")
			m_strUserName = value;
		else if(name == "uri")
			m_strDigestUri = value;
		else if(name == "qop")
			m_strQop = value;
		else if(name == "cnonce")
			m_strCNonce = value;
		else if(name == "nonce")
			m_strNonce = value;
		else if(name == "realm")
			m_strRealm = value;
		else if(name == "nc")
			m_strNonceCount = value;
		else if(name == "response")
			m_strResponse = value;
		else if(name == "opaque")
			m_strOpaque = value;
		if(*p != COMMA)
			break;
		p++;c++;
	}
	return c;	
}
mystring CSIPProxyAuthorization::Encode()
{
	mystring en;
	bool comma = false;
	en = "Proxy-Authorization: Digest ";
	if(m_strUserName.empty() == false)
	{
		en += "username=\"" + m_strUserName + "\"";
		comma = true;
	}
	if(m_strRealm.empty() == false)
	{
		if(comma)
			en += ",realm=\"" + m_strRealm + "\"";
		else
		{
			en += "realm=\"" + m_strRealm + "\"";
			comma = true;
		}
	}
	if(m_strNonce.empty() == false)
	{
		if(comma)
			en += ",nonce=\"" + m_strNonce + "\"";
		else
		{
			en += "nonce=\"" + m_strNonce + "\"";
			comma = true;
		}
	}
	if(m_strDigestUri.empty() == false)
	{
		if(comma)
			en += ",uri=\"" + m_strDigestUri + "\"";
		else
		{
			en += "uri=\"" + m_strDigestUri + "\"";
			comma = true;
		}
	}
	if(m_strQop.empty() == false)
	{
		if(comma)
			en += ",qop=\"" + m_strQop + "\"";
		else
		{
			en += "qop=\"" + m_strQop + "\"";
			comma = true;
		}
	}
	if(m_strCNonce.empty() == false)
	{
		if(comma)
			en += ",cnonce=\"" + m_strCNonce + "\"";
		else
		{
			en += "cnonce=\"" + m_strCNonce + "\"";
			comma = true;
		}
	}
	if(m_strNonceCount.empty() == false)
	{
		if(comma)
			en += ",nc=\"" + m_strNonceCount + "\"";
		else
		{
			en += "nc=\"" + m_strNonceCount + "\"";
			comma = true;
		}
	}
	if(m_strResponse.empty() == false)
	{
		if(comma)
			en += ",response=\"" + m_strResponse + "\"";
		else
		{
			en += "response=\"" + m_strResponse + "\"";
			comma = true;
		}
	}
	if(m_strOpaque.empty() == false)
	{
		if(comma)
			en += ",opaque=\"" + m_strOpaque + "\"";
		else
		{
			en += "opaque=\"" + m_strOpaque + "\"";
			comma = true;
		}
	}
	return en;
}

mystring CSIPProxyAuthorization::EncodeNoName()
{
	mystring en;
	bool comma = false;	
	en = "Digest ";
	if(m_strUserName.empty() == false)
	{
		en += "username='\"" + m_strUserName + "\"";
		comma = true;
	}
	if(m_strRealm.empty() == false)
	{
		if(comma)
			en += ",realm=\"" + m_strRealm + "\"";
		else
		{
			en += "realm=\"" + m_strRealm + "\"";
			comma = true;
		}
	}
	if(m_strNonce.empty() == false)
	{
		if(comma)
			en += ",nonce=\"" + m_strNonce + "\"";
		else
		{
			en += "nonce=\"" + m_strNonce + "\"";
			comma = true;
		}
	}
	if(m_strDigestUri.empty() == false)
	{
		if(comma)
			en += ",uri=\"" + m_strDigestUri + "\"";
		else
		{
			en += "uri=\"" + m_strDigestUri + "\"";
			comma = true;
		}
	}
	if(m_strQop.empty() == false)
	{
		if(comma)
			en += ",qop=\"" + m_strQop + "\"";
		else
		{
			en += "qop=\"" + m_strQop + "\"";
			comma = true;
		}
	}
	if(m_strCNonce.empty() == false)
	{
		if(comma)
			en += ",cnonce=\"" + m_strCNonce + "\"";
		else
		{
			en += "cnonce=\"" + m_strCNonce + "\"";
			comma = true;
		}
	}
	if(m_strNonceCount.empty() == false)
	{
		if(comma)
			en += ",nc=\"" + m_strNonceCount + "\"";
		else
		{
			en += "nc=\"" + m_strNonceCount + "\"";
			comma = true;
		}
	}
	if(m_strResponse.empty() == false)
	{
		if(comma)
			en += ",response=\"" + m_strResponse + "\"";
		else
		{
			en += "response=\"" + m_strResponse + "\"";
			comma = true;
		}
	}
	if(m_strOpaque.empty() == false)
	{
		if(comma)
			en += ",opaque=\"" + m_strOpaque + "\"";
		else
		{
			en += "opaque=\"" + m_strOpaque + "\"";
			comma = true;
		}
	}
	return en;
}
CSIPProxyAuthorization& CSIPProxyAuthorization::operator=(const CSIPProxyAuthorization& rhs)
{
	Clear();
	m_strUserName = rhs.m_strUserName;
	m_strDigestUri = rhs.m_strDigestUri;
	m_strQop = rhs.m_strQop;
	m_strCNonce = rhs.m_strCNonce;
	m_strNonceCount = rhs.m_strNonceCount;
	m_strResponse = rhs.m_strResponse;
	m_strRealm = rhs.m_strRealm;
	m_strNonce = rhs.m_strNonce;
	m_strOpaque = rhs.m_strOpaque;
	return *this;
}
bool CSIPProxyAuthorization::operator==(const CSIPProxyAuthorization& other) const
{	
	if(m_strUserName != other.m_strUserName)
		return false;
	if(m_strDigestUri != other.m_strDigestUri)
		return false;
	if(m_strQop != other.m_strQop)
		return false;
	if(m_strCNonce != other.m_strCNonce)
		return false;
	if(m_strNonceCount != other.m_strNonceCount)
		return false;
	if(m_strResponse != other.m_strResponse)
		return false;
	if(m_strRealm != other.m_strRealm)
		return false;
	if(m_strNonce != other.m_strNonce)
		return false;
	if(m_strOpaque != other.m_strOpaque)
		return false;
	return true;
}
bool CSIPProxyAuthorization::operator!=(const CSIPProxyAuthorization& other) const
{
	return !(*this == other);
}
void CSIPProxyAuthorization::Clear()
{	
	m_strUserName.erase();
	m_strDigestUri.erase();
	m_strQop.erase();
	m_strCNonce.erase();
	m_strNonceCount.erase();
	m_strResponse.erase();
	m_strRealm.erase();
	m_strNonce.erase();
	m_strOpaque.erase();
}



CSIPSequence::CSIPSequence(const CSIPSequence &seq)
{
	*this = seq;
}
void CSIPSequence::SetMethod(MethodTypes method)
{
	m_strMethod = GetMethodName(method);
}
mystring CSIPSequence::Encode()
{
	char buf[24];
	mystring en;
	en = "CSeq: ";
	sprintf(buf,"%d ",m_nSequence);
	en += buf;
	en += m_strMethod;
	return en;
}
mystring CSIPSequence::EncodeNoName()
{
	char buf[24];
	mystring en;

	sprintf(buf,"%d ",m_nSequence);
	en = buf;
	en += m_strMethod;
	return en;
}

int CSIPSequence::Parse(const char *pbody,int len)
{//CSeq = "CSeq" HCOLON 1*DIGIT LWS Method
	const char *p = pbody;
	int c = 0;
	Clear();
	mystring seq;
	while(*p != SP && *p != HTAB && *p != CR && *p != LF)
	{
		seq += *p;
		p++;
		c++;
		if(c >= len)
			return -1;
	}
	int n = SkipLWS(p,len - c);
	if(n == -1)
		return -1;
	m_nSequence = atoi(seq.c_str());
	p+=n;
	c+=n;
	while(*p != SP && *p != HTAB && *p != CR && *p != LF)
	{
		m_strMethod += *p;
		p++;
		c++;
		if(c >= len)
			return -1;
	}
	return c;
}
CSIPSequence& CSIPSequence::operator=(const CSIPSequence& rhs)
{   
	if (this != &rhs)
	{  
		m_nSequence = rhs.m_nSequence;
		m_strMethod = rhs.m_strMethod;
	}
	return *this;
}
bool CSIPSequence::operator==(const CSIPSequence& other) const
{
   if (m_nSequence != other.m_nSequence)    
   {
        return true;      
   }
   if(isEqualNoCase(m_strMethod.c_str(),other.m_strMethod.c_str()) == false)
	   return false;
   return true;
}

bool CSIPSequence::operator!=(const CSIPSequence& other) const
{
   return !(*this == other);
}

bool CSIPSequence::operator<(const CSIPSequence& other) const
{	
	if (m_nSequence < other.m_nSequence)
	{
		return true;
	}
	return false;
}


CSIPVia::CSIPVia()
{
	m_strProtocolVersion = "2.0";
	m_strProtocolName = "SIP";	
	m_strTransport = "UDP";
	m_nPort = 0;
	m_eType = Via;
	m_bNewLine = true;
}
CSIPVia::CSIPVia(const CSIPVia &via)
{
	//m_strSIPVersion = '\0';
	//m_strProtocol[0] = '\0';
	
	m_nPort = 0;
	m_eType = Via;
	*this = via;
	m_bNewLine = true;
}
CSIPVia::~CSIPVia()
{
	Clear();
}
void CSIPVia::Clear()
{
	m_strProtocolVersion.erase();
	m_strProtocolName.erase();	
	m_strTransport.erase();
	m_strHost.erase();
	m_nPort = 0;	
	m_bNewLine = true;
}
int CSIPVia::SubParse(const char *pbody, int len)
{//via-parm = sent-protocol LWS sent-by * (SEMI via-params)
//via-params = via-ttl/via-maddr/via-received/via-branch/via-extension
//sent-protocol = protocol-name SLASH protocol-version SLASH transport
//sent-by = host [COLON port]
	const char *p = pbody;
	int c = 0;
	int c1;
	Clear();
	while(1)
	{
		if(*p == SP || *p == HTAB || *p == CR || *p == LF || *p == SLASH)
			break;
		m_strProtocolName += *p;
		p++;
		c++;
		if(c >= len)
			return -1;
	}
	if(*p == SLASH)
	{
		*p++;
		c++;
	}
	else
	{
		c1 = SkipLWS(p,len - c);
		if(c1 == -1)
			return -1;
		p += c1;
		c += c1;
		if(*p != SLASH)
			return -1;
	}
	c1 = SkipLWS(p,len - c);
	if(c1 == -1)
		return -1;
	p += c1;
	c += c1;
	//protocol version
	while(1)
	{
		if(*p == SP || *p == HTAB || *p == CR || *p == LF || *p == SLASH)
			break;
		m_strProtocolVersion += *p;
		p++;
		c++;
		if(c >= len)
			return -1;
	}
	if(*p == SLASH)
	{
		*p++;
		c++;
	}
	else
	{
		c1 = SkipLWS(p,len - c);
		if(c1 == -1)
			return -1;
		p += c1;
		c += c1;
		if(*p != SLASH)
			return -1;
	}
	c1 = SkipLWS(p,len - c);
	if(c1 == -1)
		return -1;
	p += c1;
	c += c1;
	//transport
	while(1)
	{
		if(*p == SP || *p == HTAB || *p == CR || *p == LF )
			break;
		m_strTransport += *p;
		p++;
		c++;
		if(c >= len)
			return -1;
	}
	c1 = SkipLWS(p,len - c);
	if(c1 == -1)
		return -1;
	p += c1;
	c += c1;
	//sent-by
	/* analyze hostport */

#ifdef IPV6_SUPPORT
    bool ipv6 = false;
	while(1)
	{
		if(*p == '[')
		{/* ipv6 */
			ipv6 = true;
			m_strHost += *p;
			p++;
			c++;

			continue;
		}
		if(*p == ']')
		{
			ipv6 = false;
			m_strHost += *p;
			p++;
			c++;

			continue;
		}

		if(ipv6)
		{
			if(*p == SP || *p == HTAB || *p == CR || *p == LF || *p == SEMI)
				break;
		}
		else
		{
			if(*p == SP || *p == HTAB || *p == CR || *p == LF || *p == COLON || *p == SEMI)
				break;
		}
		m_strHost += *p;
		p++;
		c++;
		if(c >= len)
			return -1;
	}
#else
	while(1)
	{
		if(*p == SP || *p == HTAB || *p == CR || *p == LF || *p == COLON || *p == SEMI)
			break;
		m_strHost += *p;
		p++;
		c++;
		if(c >= len)
			return -1;
	}
#endif
	if(*p != COLON)
	{
		c1 = SkipLWS(p,len - c);
		if(c1 == -1)
			return -1;
		p += c1;
		c += c1;		
	}
	if(*p == COLON)
	{//has port
		*p++;
		c++;
		mystring port;
		while(1)
		{
			if(*p == SP || *p == HTAB || *p == CR || *p == LF || *p == SEMI)
				break;
			port += *p;
			p++;
			c++;
			if(c >= len)
				return -1;
		}
		m_nPort = atoi(port.c_str());
	}
	c1 = SkipLWS(p,len - c);
	if(c1 == -1)
		return -1;
	p += c1;
	c += c1;
	while(*p == SEMI)
	{//has parameters
		//skip SEMI
		p++;c++;
		c1 = SkipLWS(p,len - c);
		if(c1 == -1)
			return -1;
		p += c1;
		c += c1;
		c1 = m_Params.ParseVIAParams(p,len -c);
		if(c1 == -1)
			return -1;
		p+=c1;c+=c1;
		c1 = SkipLWS(p,len - c);
		if(c1 == -1)
			return -1;
		p += c1;
		c += c1;
	}
	/*
	CSIPVia *pvia = new CSIPVia;
	pvia->m_eType = this->m_eType;
	pvia->m_nPort = this->m_nPort;
	pvia->m_strHost = this->m_strHost;
	pvia->m_strProtocolName = this->m_strProtocolName;
	pvia->m_strProtocolVersion = this->m_strProtocolVersion;
	pvia->m_strTransport = this->m_strTransport;
	pvia->m_Params = this->m_Params;
	*/
	return c;
}
int CSIPVia::Parse(const char *pbody,int len)
{
	
	const char *p = pbody;
	int c = 0;
	c = SubParse(p,len);
	/*
	CSIPVia *pvia = new CSIPVia;
	c = pvia->PrivateParse(pbody,len);
	if(c >= 0)
	{
		m_Vias.push_back(pvia);
	}
	else
	{
		delete pvia;
	}
	*/
	return c;
}

int CSIPVia::PrivateParse(const char *pbody,int len)
{//Via = ("Via"/"v") HCOLON via-parm *(COMMA via-parm)
//via-parm = sent-protocol LWS sent-by * (SEMI via-params)
//via-params = via-ttl/via-maddr/via-received/via-branch/via-extension
//sent-protocol = protocol-name SLASH protocol-version SLASH transport
	Clear();
	const char *p = pbody;
	int c = 0,c1;
	while(1)
	{
		c1 = SubParse(p,len -c);
		if(c1 == -1)
			return -1;
		c+=c1;
		p+=c1;
		c1 = SkipLWS(p,len - c);
		if(c1 == -1)
			return -1;
		if(c1 > 0)
		{
			p+=c1;
			c+=c1;
		}
		if(*p != COMMA)
			break;
		p++;
		c++;
	}
	return c;
}
CSIPVia& CSIPVia::operator=(const CSIPVia& rhs)
{   
	if (this != &rhs)
	{  
		m_nPort = rhs.m_nPort;
		m_strProtocolVersion = rhs.m_strProtocolVersion;
		m_strProtocolName = rhs.m_strProtocolName;
		m_strTransport = rhs.m_strTransport;
		m_strHost = rhs.m_strHost;		
		m_Params = rhs.m_Params;		
	}
	return *this;
}
bool CSIPVia::operator==(const CSIPVia& other) const
{
   if (m_nPort != other.m_nPort)    
   {
        return false;      
   }
   if(m_strProtocolName != other.m_strProtocolName)
	   return false;
   if(m_strProtocolVersion != other.m_strProtocolVersion)
	   return false;
   if(m_strTransport != other.m_strTransport)
	   return false;
   if(m_strHost.empty() == false && other.m_strHost.empty() == false)
   {
	   if(mystricmp(m_strHost.c_str(),other.m_strHost.c_str()))
		   return false;
   }
   const ParamPair *pli = m_Params.GetHeader();
   while(pli)
   {
		if(other.m_Params.GetValue(pli->m_pName))
		{
			if(strcmp(pli->m_pValue,other.m_Params.GetValue(pli->m_pName)))
				return false;
		}
		pli = pli->m_pNext;
   }
   return true;
}

bool CSIPVia::operator!=(const CSIPVia& other) const
{
   return !(*this == other);
}
void CSIPVia::SetHost(const char *phost)
{	
	m_strHost = phost;
}

mystring CSIPVia::Encode()
{
	char buf[24];
	mystring en;
	en = "Via: ";
	en += m_strProtocolName;
	en += "/";
	en += m_strProtocolVersion;
	en += "/";
	en += m_strTransport;
	en +=" ";
	en += m_strHost;
	if(m_nPort > 0)
	{
		sprintf(buf,"%d",m_nPort);
		en +=":";
		en += buf;
	}
	en +=m_Params.Encode();
	return en;
}
mystring CSIPVia::EncodeNoName()
{
	char buf[24];
	mystring en;
	en = m_strProtocolName;
	en += "/";
	en += m_strProtocolVersion;
	en += "/";
	en += m_strTransport;
	en +=" ";
	en += m_strHost;
	if(m_nPort > 0)
	{
		sprintf(buf,"%d",m_nPort);
		en +=":";
		en += buf;
	}
	en +=m_Params.Encode();
	return en;
}
mystring CSIPExpires::Encode()
{
	char buf[24];
	mystring en;
	en = "Expires: ";
	sprintf(buf,"%d",m_nExpires);
	en += buf;
	return en;
}
mystring CSIPExpires::EncodeNoName()
{
	char buf[24];
	mystring en;
	sprintf(buf,"%d",m_nExpires);
	en = buf;
	return en;
}

int CSIPExpires::Parse(const char *pbody,int len)
{
	const char *p = pbody;
	int c = 0;
	mystring seq;
	while(*p != SP && *p != HTAB && *p != CR && *p != LF)
	{
		seq += *p;
		p++;
		c++;
		if(c >= len)
			return -1;
	}
	m_nExpires = atoi(seq.c_str());
	return c;
}
CSIPExpires& CSIPExpires::operator=(const CSIPExpires& rhs)
{   
	if (this != &rhs)
	{  
		m_nExpires = rhs.m_nExpires;
	}
	return *this;
}
bool CSIPExpires::operator==(const CSIPExpires& other) const
{
   if (m_nExpires == other.m_nExpires)    
   {
        return true;      
   }
   else
   {
      return false;
   }   
   return true;
}

bool CSIPExpires::operator!=(const CSIPExpires& other) const
{
   return !(*this == other);
}

bool CSIPExpires::operator<(const CSIPExpires& other) const
{	
	if (m_nExpires < other.m_nExpires)
	{
		return true;
	}
	return false;
}



mystring CSIPMinExpires::Encode()
{
	char buf[24];
	mystring en;
	en = "Min-Expires: ";
	sprintf(buf,"%d",m_nMinExpires);
	en += buf;
	return en;
}

mystring CSIPMinExpires::EncodeNoName()
{
	char buf[24];
	mystring en;

	sprintf(buf,"%d",m_nMinExpires);
	en = buf;
	return en;
}
int CSIPMinExpires::Parse(const char *pbody,int len)
{
	const char *p = pbody;
	int c = 0;
	mystring seq;
	while(*p != SP && *p != HTAB && *p != CR && *p != LF)
	{
		seq += *p;
		p++;
		c++;
		if(c >= len)
			return -1;
	}
	m_nMinExpires = atoi(seq.c_str());
	return c;
}
CSIPMinExpires& CSIPMinExpires::operator=(const CSIPMinExpires& rhs)
{   
	if (this != &rhs)
	{  
		m_nMinExpires = rhs.m_nMinExpires;
	}
	return *this;
}
bool CSIPMinExpires::operator==(const CSIPMinExpires& other) const
{
   if (m_nMinExpires == other.m_nMinExpires)    
   {
        return true;      
   }
   else
   {
      return false;
   }   
   return true;
}

bool CSIPMinExpires::operator!=(const CSIPMinExpires& other) const
{
   return !(*this == other);
}

bool CSIPMinExpires::operator<(const CSIPMinExpires& other) const
{	
	if (m_nMinExpires < other.m_nMinExpires)
	{
		return true;
	}
	return false;
}


CSIPIPAddress::CSIPIPAddress()
{
	
}

CSIPIPAddress::CSIPIPAddress(const CSIPIPAddress &e)
{
	*this = e;
}
CSIPIPAddress::~CSIPIPAddress()
{
	Clear();
}
int CSIPIPAddress::Parse(const char *pbody,int len)
{//NATAddress: address port
	const char *p = pbody;
	int c = 0,c1;	
	mystring str;
	Clear();
	while(*p != SP)
	{
		if(*p == CR || *p == LF)
			break;
		m_strIPAddress += *p;
		p++;c++;
		if(c >= len)
			return -1;
	}
	SKIPLWS(p,len,c,c1);
	while(*p != SP)
	{
		if(*p == CR || *p == LF)
			break;
		str += *p;
		p++;c++;
		if(c >= len)
			break;
	}
	if(str.length())
		m_nPort = atoi(str.c_str());
	else
		m_nPort = 0;
	return c;	
}
mystring CSIPIPAddress::Encode()
{
	mystring en;
	en = "IPAddress: ";
	en += m_strIPAddress;
	en += " ";
	en += m_nPort;
	return en;
}

mystring CSIPIPAddress::EncodeNoName()
{
	mystring en;
	en += m_strIPAddress;
	en += " ";
	en += m_nPort;
	return en;
}

CSIPIPAddress& CSIPIPAddress::operator=(const CSIPIPAddress& rhs)
{
	Clear();
	this->m_strIPAddress = rhs.m_strIPAddress;
	this->m_nPort = rhs.m_nPort;
	return *this;
}
bool CSIPIPAddress::operator==(const CSIPIPAddress& other) const
{	
	if(this->m_strIPAddress == other.m_strIPAddress &&
		this->m_nPort == other.m_nPort)
		return true;

	return false;
}
bool CSIPIPAddress::operator!=(const CSIPIPAddress& other) const
{
	return !(*this == other);
}
void CSIPIPAddress::Clear()
{	
	this->m_strIPAddress.erase();
	this->m_nPort = 0;
}



CSIPSupported::~CSIPSupported()
{
	
}

mystring CSIPSupported::Encode()
{	
	mystring en;
	en = "Supported: ";
	en += m_strOptionTag;
	return en;
}

mystring CSIPSupported::EncodeNoName()
{	
	mystring en;
	en = m_strOptionTag;
	return en;
}
int CSIPSupported::Parse(const char *pbody,int len)
{//Supported = "Supported"/"s" HCOLON [option-tag*(COMMA option-tag)]
	m_strOptionTag.erase();
	const char *p = pbody;
	int c = 0;
	while(*p != COMMA)
	{
		if(*p == SP || *p == HTAB || *p == CR || *p == LF)
			break;
		
		m_strOptionTag += *p;
		p++;
		c++;
		if(c == len)
			return c;
	}
	return c;
}
CSIPSupported& CSIPSupported::operator=(const CSIPSupported& rhs)
{   
	m_strOptionTag = rhs.m_strOptionTag;
	return *this;
}
bool CSIPSupported::operator==(const CSIPSupported& other) const
{
	return m_strOptionTag == other.m_strOptionTag;
}

bool CSIPSupported::operator!=(const CSIPSupported& other) const
{
   return !(*this == other);
}

bool CSIPSupported::operator<(const CSIPSupported& other) const
{	
	
	return false;
}





CSIPProxyRequire::~CSIPProxyRequire()
{
	
}

mystring CSIPProxyRequire::Encode()
{	
	mystring en;
	en = "Proxy-Require: ";
	en += m_strOptionTag;
	return en;
}

mystring CSIPProxyRequire::EncodeNoName()
{	
	mystring en;
	en = m_strOptionTag;
	return en;
}
int CSIPProxyRequire::Parse(const char *pbody,int len)
{//Supported = "Supported"/"s" HCOLON [option-tag*(COMMA option-tag)]
	m_strOptionTag.erase();
	const char *p = pbody;
	int c = 0;
	while(*p != COMMA)
	{
		if(*p == SP || *p == HTAB || *p == CR || *p == LF)
			break;
		
		m_strOptionTag += *p;
		p++;
		c++;
		if(c == len)
			return c;
	}
	return c;
}
CSIPProxyRequire& CSIPProxyRequire::operator=(const CSIPProxyRequire& rhs)
{   
	m_strOptionTag = rhs.m_strOptionTag;
	return *this;
}
bool CSIPProxyRequire::operator==(const CSIPProxyRequire& other) const
{
	return m_strOptionTag == other.m_strOptionTag;
}

bool CSIPProxyRequire::operator!=(const CSIPProxyRequire& other) const
{
   return !(*this == other);
}

bool CSIPProxyRequire::operator<(const CSIPProxyRequire& other) const
{	
	
	return false;
}

mystring CSIPMaxForwards::Encode()
{
	char buf[24];
	mystring en;
	en = "Max-Forwards: ";
	sprintf(buf,"%d",m_nMaxForwards);
	en += buf;
	return en;
}

mystring CSIPMaxForwards::EncodeNoName()
{
	char buf[24];
	mystring en;
	sprintf(buf,"%d",m_nMaxForwards);
	en = buf;
	return en;
}
int CSIPMaxForwards::Parse(const char *pbody,int len)
{
	const char *p = pbody;
	int c = 0;
	mystring seq;
	while(*p != SP && *p != HTAB && *p != CR && *p != LF)
	{
		seq += *p;
		p++;
		c++;
		if(c >= len)
			return -1;
	}
	m_nMaxForwards = atoi(seq.c_str());
	return c;
}
CSIPMaxForwards& CSIPMaxForwards::operator=(const CSIPMaxForwards& rhs)
{   
	if (this != &rhs)
	{  
		m_nMaxForwards = rhs.m_nMaxForwards;
	}
	return *this;
}
bool CSIPMaxForwards::operator==(const CSIPMaxForwards& other) const
{
   if (m_nMaxForwards == other.m_nMaxForwards)    
   {
        return true;      
   }
   else
   {
      return false;
   }   
   return true;
}

bool CSIPMaxForwards::operator!=(const CSIPMaxForwards& other) const
{
   return !(*this == other);
}

bool CSIPMaxForwards::operator<(const CSIPMaxForwards& other) const
{	
	if (m_nMaxForwards < other.m_nMaxForwards)
	{
		return true;
	}
	return false;
}




mystring CSIPContentLength::Encode()
{
	char buf[24];
	mystring en;
	en = "ContentLength: ";
	if(m_nContentLength == -1)
		en +="...";
	else
	{
		sprintf(buf,"%d",m_nContentLength);
		en += buf;
	}
	return en;
}

mystring CSIPContentLength::EncodeNoName()
{
	char buf[24];
	mystring en;
	if(m_nContentLength == -1)
		en ="...";
	else
	{
		sprintf(buf,"%d",m_nContentLength);
		en = buf;
	}
	return en;
}

int CSIPContentLength::Parse(const char *pbody,int len)
{
	const char *p = pbody;
	int c = 0;
	mystring seq;
	while(*p != SP && *p != HTAB && *p != CR && *p != LF)
	{
		seq += *p;
		p++;
		c++;
		if(c >= len)
			return -1;
	}
	m_nContentLength = atoi(seq.c_str());
	return c;
}
CSIPContentLength& CSIPContentLength::operator=(const CSIPContentLength& rhs)
{   
	if (this != &rhs)
	{  
		m_nContentLength = rhs.m_nContentLength;
	}
	return *this;
}
bool CSIPContentLength::operator==(const CSIPContentLength& other) const
{
   if (m_nContentLength == other.m_nContentLength)    
   {
        return true;      
   }
   else
   {
      return false;
   }   
   return true;
}

bool CSIPContentLength::operator!=(const CSIPContentLength& other) const
{
   return !(*this == other);
}

bool CSIPContentLength::operator<(const CSIPContentLength& other) const
{	
	if (m_nContentLength < other.m_nContentLength)
	{
		return true;
	}
	return false;
}



CSIPNameAddr::CSIPNameAddr()
{
//	m_strDisplayName.erase();
}
CSIPNameAddr::CSIPNameAddr(const CSIPNameAddr &addr)
{	
	*this = addr;
}
CSIPNameAddr::~CSIPNameAddr()
{
	Clear();
}
void CSIPNameAddr::SetDisplayName(const char *pname)
{	
	m_strDisplayName = pname;
}


void CSIPNameAddr::Clear()
{
	m_strDisplayName = "";
	m_Uri.Clear();
}

int CSIPNameAddr::Parse(const char *pbody,int len)
{//name-addr = [display-name]LAQUOT addr-spec RAQUOT
//addr-spec = SIP-URI/SIPS-URI/absoluteRUI
//display-name = *(token LWS)/quoted-mystring
	Clear();
	const char *p = pbody;
	const char *p1;
	int c = 0;
	int c1;
	//get display name
	//skip SWL
	c1 = SkipLWS(p,len - c);
	if(c1 == -1)
		return -1;
	p+=c1;
	c+=c1;
	if(*p == '\"')
	{//quoted-mystring
		p++;c++;//skip '\"'
		c1 = SkipLWS(p,len - c);
		if(c1 == -1)
			return -1;
		p+=c1;
		c+=c1;

		//find next "		
		while(*p != '\"')
		{	
			if(*p != CR && *p != LF)
				m_strDisplayName += *p;
			p++;
			c++;
			if(c >= len)
				return -1;
		}
		//skip \"
		p++;
		c++;
	}
	else
	{
		if(*p != LAQUOT)
		{//has display-name = *(tocken LWS)
			//or direct addr-spec
			//find ':' or '<'
			c1 = c;
			p1 = p;
			while(1)
			{
				if(*p1 == LAQUOT || *p1 == ':')
					break;
				else if(*p1 == CR || *p1 == LF)
					break;
				p1++;
				c1++;
				if(c1 >= len)
					return -1;
			}
			if(*p1 == ':')
			{//addr-spec
				c1 = m_Uri.Parse(p,len-c);
				if(c1 == -1)
					return -1;
				p+=c1;
				c+=c1;
				c1 = SkipLWS(p,len - c);
				if(c1 == -1)
					return -1;
				p+=c1;
				c+=c1;
				return c;
			}
			m_strDisplayName += *p;
			p++;c++;
			if(c >= len)
				return -1;
			c1 = SkipLWS(p,len - c);
			if(c1 == -1)
				return -1;
			p+=c1;
			c+=c1;
		}
	}
	c1 = SkipLWS(p,len - c);
	if(c1 == -1)
		return -1;
	p+=c1;
	c+=c1;

	if(*p != LAQUOT)
		return -1;
	//skip LAQUOT
	p++;c++;
	//we just support SIP-URI/SIP-URI

	c1 = SkipLWS(p,len - c);
	if(c1 == -1)
		return -1;
	p+=c1;
	c+=c1;

	//find RAQUOT
	p1 = p;
	c1 = c;
	while(*p1 != RAQUOT)
	{
		p1++;
		c1++;
		if(c1 >= len)
			return -1;
	}
	c1 = m_Uri.Parse(p,c1-c);
	if(c1 == -1)
		return -1;
	p+=c1;
	c+=c1;
	c1 = SkipLWS(p,len - c);
	if(c1 == -1)
		return -1;
	p+=c1;
	c+=c1;
	if(*p != RAQUOT)
		return -1;
	p++;
	c++;

	c1 = SkipLWS(p,len - c);
	if(c1 == -1)
		return -1;
	p+=c1;
	c+=c1;
	return c;


}
mystring CSIPNameAddr::Encode()
{
	mystring en;
	if(m_strDisplayName.empty() == false)
	{	
		en = "\"";
		en +=m_strDisplayName;
		en += "\"";
	
	}
	en +="<";
	en += m_Uri.Encode();
	en +=">";
	return en;
}
CSIPNameAddr& CSIPNameAddr::operator=(const CSIPNameAddr& rhs)
{   
	if (this != &rhs)
	{  
		m_strDisplayName = rhs.m_strDisplayName;
		
		m_Uri = rhs.m_Uri;		
	
	}
	return *this;
}
bool CSIPNameAddr::operator==(const CSIPNameAddr& other) const
{
   if(mystricmp(m_strDisplayName.c_str(),other.m_strDisplayName.c_str()))
	   return false;
   if(m_Uri != other.m_Uri)
	   return false;
   
   return true;
}

bool CSIPNameAddr::operator!=(const CSIPNameAddr& other) const
{
   return !(*this == other);
}

CSIPContact::CSIPContact()
{
	m_bAsterisk = false;
}
CSIPContact::CSIPContact(const CSIPContact &c)
{
	m_bAsterisk = false;	
	*this = c;
}
CSIPContact::~CSIPContact()
{
	Clear();
}
void CSIPContact::Clear()
{
	m_NameAddr.Clear();
	m_bAsterisk = false;
}
int CSIPContact::Parse(const char *pbody,int len)
{
	const char *p = pbody;
	int c = 0;
	int c1;
	Clear();
	c1 = SkipLWS(p,len - c);
	if(c1 == -1)
		return -1;
	p+=c1;
	c+=c1;
	if(*p == STAR)
	{		
		m_bAsterisk = true;
		p++;c++;
		c1 = SkipLWS(p,len - c);
		if(c1 == -1)
			return -1;
		p+=c1;
		c+=c1;
		return c;
	}	
	c1 = m_NameAddr.Parse(p,len - c);
	if(c1 == -1)
	{
		m_NameAddr.SetDisplayName("");
		c1 = m_NameAddr.Uri().Parse(p,len - c,false);
		if(c1 == -1)
			return -1;
		p+=c1;
		c+=c1;
	}
	else
	{
		p+=c1;
		c+=c1;
	}
	SKIPLWS(p,len,c,c1);
	while(*p == SEMI)
	{
		p++;c++;
		SKIPLWS(p,len,c,c1);
		c1 = m_Params.ParseVIAParams(p,len - c);
		if(c1 == -1)
			return -1;
		p+=c1;
		c+=c1;
		SKIPLWS(p,len,c,c1);
	}
	return c;	
}
mystring CSIPContact::EncodeNoName()
{
	mystring en;
	if(m_bAsterisk)
	{
		en = "*";
		return en;
	}
	en = m_NameAddr.Encode();
	en += m_Params.Encode();
	return en;
}
mystring CSIPContact::Encode()
{
	mystring en;
	en = "Contact: ";
	int c = 0;
	if(m_bAsterisk)
	{
		en +="*";
		return en;
	}
	en += m_NameAddr.Encode();
	en += m_Params.Encode();
	return en;
}

CSIPContact& CSIPContact::operator=(const CSIPContact& rhs)
{
	if (this != &rhs)
	{  
		Clear();
		m_NameAddr = rhs.m_NameAddr;
		m_Params = rhs.m_Params;		
		m_bAsterisk = rhs.m_bAsterisk;
	}
	return *this;
}
bool CSIPContact::operator==(const CSIPContact& other) const
{
	
	if(m_bAsterisk != other.m_bAsterisk)
		return false;
	if(m_NameAddr != other.m_NameAddr)
		return false;
	return true;
}
bool CSIPContact::operator!=(const CSIPContact& other) const
{
	 return !(*this == other);
}

CSIPContentType::CSIPContentType()
{
	m_eType = ContentType;
}
CSIPContentType::CSIPContentType(const char *ptype,const char *psubtype)
{
	if(ptype)
		m_strType = ptype;
	if(psubtype)
		m_strSubType = psubtype;
}
CSIPContentType::CSIPContentType(const CSIPContentType &ct)
{
	*this = ct;
}
CSIPContentType::~CSIPContentType()
{
	Clear();
}
CSIPContentType& CSIPContentType::operator=(const CSIPContentType& rhs)
{
	if (this != &rhs)
	{  
		Clear();
		m_strType = rhs.m_strType;
		m_strSubType = rhs.m_strSubType;
		m_Params = rhs.m_Params;
		m_eType = rhs.m_eType;
	}
	return *this;
}
bool CSIPContentType::operator==(const CSIPContentType& other) const
{
	if(m_strType != other.m_strType)
		return false;
	if(m_strSubType != other.m_strSubType)
		return false;
	if(m_Params != other.m_Params)
		return false;
	return true;
}
bool CSIPContentType::operator!=(const CSIPContentType& other) const
{
	return !(*this == other);
}

int CSIPContentType::Parse(const char *pbody,int len)
{
	const char *p = pbody;
	int c1,c=0;	
	while(*p != SLASH)
	{
		if(*p == SP || *p == HTAB || *p == CR || *p == LF)
			break;
		
		if(istoken(*p) == false)
			break;
		m_strType += *p;
		p++;
		c++;
		if(c >= len)
			return -1;
	}

	SKIPLWS(p,len,c,c1);
	if(*p != SLASH)
		return -1;
	//skip /
	p++;
	c++;
	SKIPLWS(p,len,c,c1);	
	while(*p != SEMI)
	{
		if(*p == SP || *p == HTAB || *p == CR || *p == LF)
			break;
		
		if(istoken(*p) == false)
			break;
		m_strSubType += *p;
		p++;
		c++;
		if(c == len)
			return c;
	}

	SKIPLWS(p,len,c,c1);
	//parse  parameters,
	while(*p == SEMI)
	{
		p++;c++;
		c1 = m_Params.ParseVIAParams(p,len - c);
		if(c1 == -1)
			return -1;
		p+=c1;
		c+=c1;
		SKIPLWS(p,len,c,c1);
	}
	return c;
}

mystring CSIPContentType::Encode()
{
	mystring en;
	en = "Content-Type: ";
	en += m_strType;
	en += "/";
	en += m_strSubType;
	en += m_Params.Encode();
	return en;
}

mystring CSIPContentType::EncodeNoName()
{
	mystring en;
	en = m_strType;
	en += "/";
	en += m_strSubType;
	en += m_Params.Encode();
	return en;
}
void CSIPContentType::SetType(const char *ptype)
{
	m_strType = ptype;
}
void CSIPContentType::SetSubType(const char *psubtype)
{
	m_strSubType = psubtype;
}
void CSIPContentType::Clear()
{
	m_strType.erase();
	m_strSubType.erase();
	m_Params.Clear();
}


CSIPAccept::CMediaRange::CMediaRange()
{
}
CSIPAccept::CMediaRange::CMediaRange(const CSIPAccept::CMediaRange &mr)
{
	*this = mr;
}
CSIPAccept::CMediaRange::~CMediaRange()
{
	Clear();
}
CSIPAccept::CMediaRange& CSIPAccept::CMediaRange::operator=(const CSIPAccept::CMediaRange& rhs)
{
	m_strType = rhs.m_strType;
	m_strSubType = rhs.m_strSubType;
	m_Params = rhs.m_Params;
	return *this;
}
void CSIPAccept::CMediaRange::Clear()
{
	m_strType.erase();
	m_strSubType.erase();
	m_Params.Clear();
}

int CSIPAccept::CMediaRange::Parse(const char *pbody,int len,bool param)
{//accept-range = media-range * (SEMI accept-param)
//media-range = ("*/*" / (m-type SLASH "*") / (m-type SLASH m-subtype)) * (SEMI m-parameter)
	const char *p = pbody;
	int c1,c=0;
	mystring name;
	Clear();
	while(*p != SLASH)
	{
		if(*p == SP || *p == HTAB || *p == CR || *p == LF)
			break;
			
		m_strType += *p;
		p++;
		c++;
		if(c >= len)
			return -1;
	}
	SKIPLWS(p,len,c,c1);
	if(*p != SLASH)
		return -1;
	//skip /
	p++;
	c++;
	SKIPLWS(p,len,c,c1);
	while(*p != SEMI)
	{
		if(*p == SP || *p == HTAB || *p == CR || *p == LF || *p == COMMA)
			break;
		
	
		m_strSubType += *p;
		p++;
		c++;
		if(c == len)
			return c;
	}

	SKIPLWS(p,len,c,c1);
	if(param == false)
		return c;
	while(*p == SEMI)
	{
		p++;c++;
		SKIPLWS(p,len,c,c1);
		c1 = m_Params.ParseVIAParams(p,len - c);
		if(c1 == -1)
			return -1;
		p+=c1;
		c+=c1;
		if(c >= len)
			return c;
		SKIPLWS(p,len,c,c1);
	}
	return c;
}
mystring CSIPAccept::CMediaRange::Encode()
{
	mystring en;
	en = m_strType;
	en += "/";
	en += m_strSubType;
	en += m_Params.Encode();
	return en;
}
mystring CSIPAccept::Encode()
{
	mystring en;
	en = "Accept: ";
	if(m_MediaRange.GetParams().GetSize()>0)
	{
		en += "<";
		en += m_MediaRange.Encode();
		en += ">";
	}
	else
		en += m_MediaRange.Encode();
	en += m_Params.Encode();
	return en;
}
mystring CSIPAccept::EncodeNoName()
{
	mystring en;
	if(m_MediaRange.GetParams().GetSize()>0)
	{
		en += "<";
		en += m_MediaRange.Encode();
		en += ">";
	}
	else
		en += m_MediaRange.Encode();
	en += m_Params.Encode();
	return en;
}
CSIPAccept& CSIPAccept::operator=(const CSIPAccept& rhs)
{
	m_MediaRange = rhs.m_MediaRange;
	m_Params = rhs.m_Params;
	return *this;
}
void CSIPAccept::Clear()
{
	m_Params.Clear();
	m_MediaRange.Clear();
}


CSIPAccept::CSIPAccept()
{
	m_eType = Accept;
}
CSIPAccept::CSIPAccept(const CSIPAccept &ct)
{
	*this = ct;
}
CSIPAccept::~CSIPAccept()
{
	Clear();
}

bool CSIPAccept::operator==(const CSIPAccept& other) const
{

	/*
	if(isEqualNoCase(m_strType.c_str(),other.m_strType.c_str()) == false)
		return false;
	if(isEqualNoCase(m_strSubType.c_str(),other.m_strSubType.c_str()) == false)
		return false;
	if(m_Params != other.m_Params)
		return false;
		*/
	return false;
}
bool CSIPAccept::operator!=(const CSIPAccept& other) const
{
	return !(*this == other);
}

int CSIPAccept::Parse(const char *pbody,int len)
{
//accept-range = media-range * (SEMI accept-param)
//media-range = ("*/*" / (m-type SLASH "*") / (m-type SLASH m-subtype)) * (SEMI m-parameter)
	const char *p = pbody;
	const char *p1;
	int c = 0,c1;
	if(*p == LAQUOT)
	{
		p1= p;
		c1 = c;
		//find RAQUOT
		while(*p1 != RAQUOT)
		{
			p1++;
			c1++;
			if(c1 >= len)
				return -1;
		}
		c1 = m_MediaRange.Parse(p,c1 - c);
		if(c1 == -1)
			return -1;
		p = p1;
		c = p - pbody;
		p++;
		c++;
		SKIPLWS(p,len,c,c1);
	}
	else
	{
		c1 = m_MediaRange.Parse(p,len - c);
		if(c1 == -1)
			return -1;
		p+=c1;
		c+=c1;
		SKIPLWS(p,len,c,c1);
	}
	
	SKIPLWS(p,len,c,c1);
	while(*p == SEMI)
	{
		p++;c++;
		SKIPLWS(p,len,c,c1);
		c1 = m_Params.ParseVIAParams(p,len-c);
		if(c1 == -1)
			return -1;
		c+=c1;
		p+=c1;
		SKIPLWS(p,len,c,c1);		
	}	
	return c;	
}


CSIPContent::CSIPContent()
{
	m_pContent = NULL;
	m_nLength = 0;
	m_pContentType = NULL;
}
CSIPContent::CSIPContent(const CSIPContentType &type)
{
	m_pContent = NULL;
	m_nLength = 0;
	m_pContentType = NULL;
	SetContentType(type);
}

CSIPContent::CSIPContent(const CSIPContent &c)
{	
	m_pContent = NULL;
	m_nLength = 0;
	m_pContentType = NULL;
	*this = c;
}
CSIPContent::~CSIPContent()
{
	Clear();	
}
void CSIPContent::SetContentType(const CSIPContentType &type)
{
	if(m_pContentType)
		*m_pContentType = type; 
	else
		m_pContentType = new CSIPContentType(type);
}
void CSIPContent::SetContent(const char *pcontent,int len)
{
	Clear();
	m_pContent = new char[len+1];
	memcpy(m_pContent,pcontent,len);
	m_pContent[len] = '\0';
	m_nLength = len;
}
mystring CSIPContent::Encode()
{
	mystring en;
	if(m_pContent)
		en = m_pContent;
	return en;
}
void CSIPContent::Clear()
{
	if(m_pContent)
	{
		delete[] m_pContent;
		m_pContent = NULL;
	}
	m_nLength = 0;
	if(m_pContentType)
	{
		delete m_pContentType;
		m_pContentType = NULL;
	}
}
CSIPContent& CSIPContent::operator=(const CSIPContent& rhs)
{
	if(this != &rhs)
	{
		Clear();
		if(rhs.m_nLength > 0 && rhs.m_pContent)
		{
			m_pContent = new char[rhs.m_nLength+1];
			memcpy(m_pContent,rhs.m_pContent,rhs.m_nLength);
			m_nLength = rhs.m_nLength;
			m_pContent[m_nLength] = '\0';			
		}
		if(rhs.m_pContentType)
		{
			m_pContentType = new CSIPContentType(*rhs.m_pContentType);
		}
	}
	return *this;
}
bool CSIPContent::operator==(const CSIPContent& other) const
{
	if(this->m_nLength != other.m_nLength)
		return false;
	if(memcmp(this->m_pContent,other.m_pContent,other.m_nLength))
		return false;
	if(m_pContentType && other.m_pContentType)
	{
		if(*m_pContentType != *other.m_pContentType)
			return false;
	}
	else if(m_pContentType != other.m_pContentType)
		return false;
	return true;
}
bool CSIPContent::operator!=(const CSIPContent& other) const
{
	return !(*this == other);
}

CSIPTranslate::CSIPTranslate()
{
	m_pNA = NULL;
}
CSIPTranslate::CSIPTranslate(const CSIPTranslate &c)
{
	m_pNA = new CSIPNameAddr(*c.GetNameAddr());
}
CSIPTranslate::~CSIPTranslate()
{
	Clear();
}
int CSIPTranslate::Parse(const char *pbody,int len)
{
	if(m_pNA == NULL)
		m_pNA = new CSIPNameAddr();

	return m_pNA->Parse(pbody,len);	
}
mystring CSIPTranslate::Encode()
{
	mystring en;
	if(m_pNA)
	{
		en = "Translate: ";
		en += m_pNA->Encode();
	}
	return en;
}

mystring CSIPTranslate::EncodeNoName()
{
	mystring en;
	if(m_pNA)
	{	
		en = m_pNA->Encode();
	}
	return en;
}
CSIPTranslate& CSIPTranslate::operator=(const CSIPTranslate& rhs)
{
	if(this != &rhs)
	{
		if(rhs.m_pNA)
		{
			if(m_pNA)
				*m_pNA = *rhs.m_pNA;
			else
			{
				m_pNA = new CSIPNameAddr(*rhs.m_pNA);
			}
		}
		else
		{
			if(m_pNA)
			{
				delete m_pNA;
				m_pNA = NULL;
			}
		}
	}
	return *this;
}
bool CSIPTranslate::operator==(const CSIPTranslate& other) const
{
	if(other.m_pNA && this->m_pNA)
	{
		return *other.m_pNA == *this->m_pNA;
	}
	else if(other.m_pNA == NULL && this->m_pNA == NULL)
		return true;
	else
		return false;
}
bool CSIPTranslate::operator!=(const CSIPTranslate& other) const
{
	return !(*this == other);
}
void CSIPTranslate::Clear()
{
	if(m_pNA)
	{
		delete m_pNA;
		m_pNA = NULL;
	}
}
void CSIPTranslate::AddNameAddr(CSIPNameAddr &na)
{
	if(m_pNA)
		*m_pNA = na;
	else
	{
		m_pNA = new CSIPNameAddr(na);
	}
}

char CSIPSubscriptionState::m_sStates[CSIPSubscriptionState::maxstates][11] = {
	"unknown",
	"pending",
	"active",
	"terminated",
};

CSIPSubscriptionState::CSIPSubscriptionState()
{
	m_eState = terminated;
	m_eType = SubscriptionState;
}

CSIPSubscriptionState::CSIPSubscriptionState(CSIPSubscriptionState::States s)
{
	m_eState = s;
	m_eType = SubscriptionState;
}
CSIPSubscriptionState::CSIPSubscriptionState(const CSIPSubscriptionState &c)
{
	*this = c;
}
CSIPSubscriptionState::~CSIPSubscriptionState()
{
	Clear();
}
int CSIPSubscriptionState::Parse(const char *pbody,int len)
{//Subscription-State: active
	const char *p = pbody;
	int c1,c = 0;
	Clear();
	while(*p != SEMI)
	{
		if(*p == SP || *p == HTAB || *p == CR || *p == LF)
				break;
		if(istoken(*p) == false)
			break;
		m_strState += *p;		
		p++;
		c++;
		if(c >= len)
			return -1;
	}
	int n = SkipLWS(p,len - c);
	if(n == -1)
		return -1;

	for(int i=1;i<maxstates;i++)
	{
		if(mystricmp(m_strState.c_str(),m_sStates[i]) == 0)
		{
			m_eState = (States)i;
			break;
		}
	}
	while(*p == SEMI)
	{
		p++;c++;
		SKIPLWS(p,len,c,c1);
		c1 = m_Params.ParseURIParams(p,len - c);
		if(c1 == -1)
			return -1;
		p+=c1;
		c+=c1;
		SKIPLWS(p,len,c,c1);
	}
	return c;
}
mystring CSIPSubscriptionState::Encode()
{
	mystring en;
	en = "Subscription-State: ";
	if(m_eState > unknown && m_eState < maxstates)
		en +=m_sStates[m_eState];
	else
		en +="terminated";
	en += m_Params.Encode();
	return en;
}

mystring CSIPSubscriptionState::EncodeNoName()
{
	mystring en;
	if(m_eState > unknown && m_eState < maxstates)
		en =m_sStates[m_eState];
	else
		en ="terminated";
	en += m_Params.Encode();
	return en;
}

CSIPSubscriptionState& CSIPSubscriptionState::operator=(const CSIPSubscriptionState& rhs)
{
	if(this != &rhs)
	{
		this->m_eState = rhs.m_eState;
		this->m_eType = rhs.m_eType;
		this->m_Params = rhs.m_Params;
		this->m_strState = rhs.m_strState;
	}
	return *this;
}
bool CSIPSubscriptionState::operator==(const CSIPSubscriptionState& other) const
{
	if(this->m_eState != other.m_eState)
		return false;
	else if(this->m_eType != other.m_eType)
		return false;
	else if(this->m_Params != other.m_Params)
		return false;
	return true;
}
bool CSIPSubscriptionState::operator!=(const CSIPSubscriptionState& other) const
{
	return !(*this == other);
}
void CSIPSubscriptionState::Clear()
{
	m_strState.erase();
	m_eState = terminated;
	m_Params.Clear();

}

char CSIPEvent::m_sEvents[CSIPEvent::enMaxSubscribeMethod][32] = {
	"register",
	"subscribe",
	"presence",
	"record",
	"heartbeat",
	"lock",
	"unlock",
	"unknown"
};

CSIPEvent::CSIPEvent()
{
	m_eEvent = enSubscribeMethodPresence;
	m_eType = CSIPHeader::Event;
}

CSIPEvent::CSIPEvent(CSIPEvent::Events e)
{
	m_eEvent = e;
	m_eType = CSIPHeader::Event;
}
CSIPEvent::CSIPEvent(const CSIPEvent &c)
{
	*this = c;
}
CSIPEvent::~CSIPEvent()
{
	Clear();
}
int CSIPEvent::Parse(const char *pbody,int len)
{
	const char *p = pbody;
	int c1,c = 0;
	Clear();
	while(*p != SEMI)
	{
		if(*p == SP || *p == HTAB || *p == CR || *p == LF)
			break;		
	
		m_strEventType += *p;
		p++;
		c++;
		if(c >= len)
		{
			m_eEvent = MatchEvent(m_strEventType);
			return c;
		}
	}
	SKIPLWS(p,len,c,c1);
	m_eEvent = MatchEvent(m_strEventType);
	while(*p == SEMI)
	{
		p++;c++;
		SKIPLWS(p,len,c,c1);
		c1 = m_Params.ParseVIAParams(p,len - c);
		if(c1 == -1)
			return -1;
		p+=c1;
		c+=c1;
		SKIPLWS(p,len,c,c1);
	}
	return c;	
}
CSIPEvent::Events CSIPEvent::MatchEvent(mystring &str)
{
	for(int i=0;i<enMaxSubscribeMethod;i++)
	{
		if(str == m_sEvents[i])
			return (Events)i;
	}
	return enSubscribeMethodUnknown;
}

mystring CSIPEvent::Encode()
{
	mystring en;
	en = "Event: ";
	if(m_eEvent >= 0 && m_eEvent < enMaxSubscribeMethod)
		en +=m_sEvents[m_eEvent];
	else
		en +="unknown";
	en += m_Params.Encode();
	return en;
}

mystring CSIPEvent::EncodeNoName()
{
	mystring en;
	if(m_eEvent >= 0 && m_eEvent < enMaxSubscribeMethod)
		en +=m_sEvents[m_eEvent];
	else
		en +="unknown";
	en += m_Params.Encode();
	return en;
}

CSIPEvent& CSIPEvent::operator=(const CSIPEvent& rhs)
{
	if(this != &rhs)
	{
		this->m_eEvent = rhs.m_eEvent;
		this->m_eType = rhs.m_eType;
		this->m_Params = rhs.m_Params;
		this->m_strEventType = rhs.m_strEventType;
	}
	return *this;
}
bool CSIPEvent::operator==(const CSIPEvent& other) const
{
	if(this->m_eEvent != other.m_eEvent)
		return false;
	else if(this->m_eType != other.m_eType)
		return false;
	else if(this->m_Params != other.m_Params)
		return false;
	return true;
}
bool CSIPEvent::operator!=(const CSIPEvent& other) const
{
	return !(*this == other);
}
void CSIPEvent::Clear()
{
	m_eEvent = enSubscribeMethodUnknown;
	m_Params.Clear();
	m_strEventType.erase();
}



CSIPAllowEvents::CSIPAllowEvents()
{
	m_eType = CSIPHeader::AllowEvents;
}

CSIPAllowEvents::CSIPAllowEvents(const CSIPAllowEvents &c)
{
	*this = c;
}
CSIPAllowEvents::~CSIPAllowEvents()
{
	Clear();
}
int CSIPAllowEvents::Parse(const char *pbody,int len)
{//RFC3265
	const char *p = pbody;
	int c1,c=0;
	Clear();
	while(*p != COMMA)
	{
		if(*p == SP || *p == HTAB || *p == CR || *p == LF || *p == SEMI)
			break;
		
		for(int i=0;i<sizeof(g_Reserved);i++)
		{
			if(*p == g_Reserved[i] && *p != '+')
				return -1;
		}
		m_strEvent += *p;
		p++;
		c++;
		if(c == len)
		{			
			return c;
		}
	}
	SKIPLWS(p,len,c,c1);
	return c;
}
mystring CSIPAllowEvents::Encode()
{//RFC3265
	mystring en;
	en = "Allow-Events: ";
	en += m_strEvent;
	return en;
}
mystring CSIPAllowEvents::EncodeNoName()
{//RFC3265
	mystring en;
	en = m_strEvent;
	return en;
}
CSIPAllowEvents& CSIPAllowEvents::operator=(const CSIPAllowEvents& rhs)
{
	m_strEvent = rhs.m_strEvent;
	return *this;
}
bool CSIPAllowEvents::operator==(const CSIPAllowEvents& other) const
{
	return m_strEvent == other.m_strEvent;	
}
bool CSIPAllowEvents::operator!=(const CSIPAllowEvents& other) const
{
	return !(*this == other);
}
void CSIPAllowEvents::Clear()
{
	m_strEvent.erase();
}

CSIPRequestLine::CSIPRequestLine(MethodTypes method):
		m_Uri(),
		m_eMethod(method),
		m_strSIPVersion("SIP/2.0")
{
	if(m_eMethod >=0 && m_eMethod < MAX_METHODS)
		m_strMethod = GetMethodName(m_eMethod);
	else
		m_strMethod = "UNKNOWN";
}

CSIPRequestLine::CSIPRequestLine(const CSIPRequestLine &line)	
{
	*this = line;
}
CSIPRequestLine::~CSIPRequestLine()
{
	Clear();
}
void CSIPRequestLine::SetMethod(MethodTypes method)
{
	m_eMethod = method;
	assert(m_eMethod >=0 && m_eMethod < MAX_METHODS);
	m_strMethod = GetMethodName(m_eMethod);
}
void CSIPRequestLine::Clear()
{
	m_strMethod.erase();
	m_Uri.Clear();
	m_eMethod = UNKNOWN;
	m_strSIPVersion.erase();// = "SIP/2.0";
}
int CSIPRequestLine::Parse(const char *pbody,int len)
{// Request-Line  =  Method SP Request-URI SP SIP-Version CRLF
	const char *p = pbody;
//char *s;
	int c = 0,c1;
	Clear();
	while(*p != SP)
	{
		if( *p == HTAB || *p == CR || *p == LF)
			return -1;
		m_strMethod += *p;
		p++;
		c++;
		if(c >= len)
			return -1;		
	}
	p++;//skip SP	
	c++;
	m_eMethod = GetMethodType(m_strMethod.c_str());
	m_Uri.Clear();
	c1 = m_Uri.Parse(p,len - c);
	if(c1 == -1)
		return -1;
	p+=c1;
	c+=c1;
	if(*p != SP)
		return -1;
	p++;//skip SP
	c++;
	while(*p != CR)
	{
		m_strSIPVersion += *p;
		p++;
		c++;
		if(c >= len)
			return -1;
	}	
	return c;
}
mystring CSIPRequestLine::Encode()
{
	mystring en;
	en = m_strMethod;
	en +=" ";
	en += m_Uri.Encode();
	en += " ";
	en += m_strSIPVersion;
	return en;
}

CSIPRequestLine& CSIPRequestLine::operator=(const CSIPRequestLine& rhs)
{
	if(this != &rhs)
	{
		this->m_eMethod = rhs.m_eMethod;
		this->m_strMethod = rhs.m_strMethod;
		this->m_strSIPVersion = rhs.m_strSIPVersion;
		this->m_Uri = rhs.m_Uri;
	}
	return *this;
}
bool CSIPRequestLine::operator==(const CSIPRequestLine& other) const
{
	if(this->m_eMethod != other.m_eMethod)
		return false;
	if(this->m_strMethod != other.m_strMethod)
		return false;
	else if(this->m_strSIPVersion != other.m_strSIPVersion)
		return false;
	else if(this->m_Uri != other.m_Uri)
		return false;
	return true;
}
bool CSIPRequestLine::operator!=(const CSIPRequestLine& other) const
{
	return !(*this == other);
}

CSIPStatusLine::CSIPStatusLine():
		m_nStatusCode(0),
		m_strReason(""),
		m_strSIPVersion("SIP/2.0")
{
}
CSIPStatusLine::CSIPStatusLine(const CSIPStatusLine &line)	
{
	*this = line;
}
CSIPStatusLine::~CSIPStatusLine()
{
	Clear();
}
void CSIPStatusLine::Clear()
{	
	m_nStatusCode = 0;
	m_strSIPVersion.erase();
	m_strReason = "";
}
int CSIPStatusLine::Parse(const char *pbody,int len)
{// Status-Line  =  SIP-Version SP Status-Code SP Reason-Phrase CRLF
	const char *p = pbody;
	int c = 0;
	Clear();
	while(*p != SP)
	{
		if(*p == HTAB || *p == CR || *p == LF)
			return -1;
		m_strSIPVersion += *p;
		p++;
		c++;
		if(c >= len)
			return -1;
	}
	p++;
	c++;
	mystring code;
	while(*p != SP)
	{
		if(*p == HTAB || *p == CR || *p == LF)
			break;
		code += *p;
		p++;
		c++;
		if(c >= len)
			return -1;
	}
	m_nStatusCode = atoi(code.c_str());
	if(*p == SP || *p == HTAB)
	{
		p++;
		c++;
	}
	while(c < len)
	{
		if(*p == CR && p[1] == LF)
			break;
		m_strReason += *p;
		p++;
		c++;
		if(c+2 > len)
			return -1;
	}
	return c;
}
mystring CSIPStatusLine::Encode()
{
	mystring en;
	en = m_strSIPVersion;
	en +=" ";
	char status[16];
	sprintf(status,"%d",m_nStatusCode);
	en += status;
	if(m_strReason.empty() == false)
	{
		en += " ";
		en += m_strReason;
	}
	return en;
}

CSIPStatusLine& CSIPStatusLine::operator=(const CSIPStatusLine& rhs)
{
	if(this != &rhs)
	{
		this->m_nStatusCode = rhs.m_nStatusCode;
		this->m_strSIPVersion = rhs.m_strSIPVersion;
		this->m_strReason = rhs.m_strReason;
	}
	return *this;
}
bool CSIPStatusLine::operator==(const CSIPStatusLine& other) const
{
	if(this->m_nStatusCode != other.m_nStatusCode)
		return false;
	else if(this->m_strSIPVersion != other.m_strSIPVersion)
		return false;
	else if(this->m_strReason != other.m_strReason)
		return false;
	return true;
}
bool CSIPStatusLine::operator!=(const CSIPStatusLine& other) const
{
	return !(*this == other);
}

CSIPContentEncoding::CSIPContentEncoding()
{
}
CSIPContentEncoding::CSIPContentEncoding(const CSIPContentEncoding &ct)
{
	*this = ct;
}
CSIPContentEncoding::~CSIPContentEncoding()
{
	Clear();
}
CSIPContentEncoding& CSIPContentEncoding::operator=(const CSIPContentEncoding& rhs)
{
	m_strContentCoding = rhs.m_strContentCoding;
	return *this;
}

int CSIPContentEncoding::Parse(const char *pbody,int len)
{
	const char *p = pbody;
	int c=0;
	Clear();
	while(*p != COMMA)
	{
		if(*p == SP || *p == HTAB || *p == CR || *p == LF || *p == SEMI)
			break;
		
		for(int i=0;i<sizeof(g_Reserved);i++)
		{
			if(*p == g_Reserved[i])
				return -1;
		}
		m_strContentCoding += *p;
		p++;
		c++;
		if(c == len)
		{			
			return c;
		}
	}
	return c;
}
mystring CSIPContentEncoding::Encode()
{
	mystring en;
	en = "Content-Encoding: ";
	en += m_strContentCoding;
	return en;
}
mystring CSIPContentEncoding::EncodeNoName()
{
	mystring en;
	en = m_strContentCoding;
	return en;
}
void CSIPContentEncoding::Clear()
{
	m_strContentCoding.erase();
}



CSIPContentDisposition::CSIPContentDisposition()
{
}
CSIPContentDisposition::CSIPContentDisposition(const CSIPContentDisposition &ct)
{
	*this = ct;
}
CSIPContentDisposition::~CSIPContentDisposition()
{
	Clear();
}
CSIPContentDisposition& CSIPContentDisposition::operator=(const CSIPContentDisposition& rhs)
{
	m_strDispType = rhs.m_strDispType;
	return *this;
}

int CSIPContentDisposition::Parse(const char *pbody,int len)
{//RFC3261 Page 228
//Content-Disposition = disp-type * (SEMI disp-param)
	const char *p = pbody;
	int c=0,c1;
	Clear();
	while(*p != SEMI)
	{
		if(*p == SP || *p == HTAB || *p == CR || *p == LF)
			break;
		
		if(istoken(*p) == false)
			break;
		m_strDispType += *p;
		p++;
		c++;
		if(c == len)
		{			
			return c;
		}
	}
	SKIPLWS(p,len,c,c1);
	while(*p == SEMI)
	{//param
		p++;c++;
		SKIPLWS(p,len,c,c1);
		c1 = m_Params.ParseVIAParams(p,len - c);
		if(c1 == -1)
			return -1;
		p+=c1;c+=c1;
		SKIPLWS(p,len,c,c1);
	}
	return c;
}
mystring CSIPContentDisposition::Encode()
{
	mystring en;
	en = "Content-Disposition: ";
	en += m_strDispType;
	en += m_Params.Encode();
	return en;
}
mystring CSIPContentDisposition::EncodeNoName()
{
	mystring en;
	en = m_strDispType;
	en += m_Params.Encode();
	return en;
}
void CSIPContentDisposition::Clear()
{
	m_strDispType.erase();
	m_Params.Clear();
}

CSIPContentLanguage::CSIPContentLanguage()
{
}
CSIPContentLanguage::CSIPContentLanguage(const CSIPContentLanguage &ct)
{
	*this = ct;
}
CSIPContentLanguage::~CSIPContentLanguage()
{
	Clear();
}
CSIPContentLanguage& CSIPContentLanguage::operator=(const CSIPContentLanguage& rhs)
{
	m_strContentLanguage = rhs.m_strContentLanguage;
	return *this;
}

int CSIPContentLanguage::Parse(const char *pbody,int len)
{
	const char *p = pbody;
	int c=0;
	Clear();
	while(*p != COMMA)
	{
		if(*p == SP || *p == HTAB || *p == CR || *p == LF || *p == SEMI)
			break;
		
		for(int i=0;i<sizeof(g_Reserved);i++)
		{
			if(*p == g_Reserved[i])
				return -1;
		}
		m_strContentLanguage += *p;
		p++;
		c++;
		if(c == len)
		{			
			return c;
		}
	}
	return c;
}
mystring CSIPContentLanguage::Encode()
{
	mystring en;
	en = "Content-Encoding: ";
	en += m_strContentLanguage;
	return en;
}
mystring CSIPContentLanguage::EncodeNoName()
{
	mystring en;
	en = m_strContentLanguage;
	return en;
}
void CSIPContentLanguage::Clear()
{
	m_strContentLanguage.erase();
}

CSIPUserAgent::CSIPUserAgent()
{
	m_eType = CSIPHeader::UserAgent;
}
CSIPUserAgent::CSIPUserAgent(const char *puag)
{
	m_eType = CSIPHeader::UserAgent;
	if(puag)
		m_strUserAgent = puag;
	else
		m_strUserAgent = "";
}
CSIPUserAgent::CSIPUserAgent(const CSIPUserAgent &e)
{
	*this = e;
}
CSIPUserAgent::~CSIPUserAgent()
{
	Clear();
}
int CSIPUserAgent::Parse(const char *pbody,int len)
{
	const char *p = pbody;
	int c1,c = 0;
	Clear();
	while(*p != COMMA)
	{
		SKIPLWS(p,len,c,c1);
		if(*p == SP || *p == HTAB || *p == CR || *p == LF || *p == SEMI)
			break;
		
		for(int i=0;i<sizeof(g_Reserved);i++)
		{
			if(*p == g_Reserved[i] && *p != '/')
				return -1;
		}
		m_strUserAgent += *p;
		p++;
		c++;
		if(c == len)
		{			
			return c;
		}
	}
	return c;
}
mystring CSIPUserAgent::Encode()
{
	mystring en;
	en = "User-Agent: ";
	en += m_strUserAgent;
	return en;
}

mystring CSIPUserAgent::EncodeNoName()
{
	mystring en;
	en = m_strUserAgent;
	return en;
}

CSIPUserAgent& CSIPUserAgent::operator=(const CSIPUserAgent& rhs)
{
	if(this != &rhs)
	{
		this->m_eType = rhs.m_eType;
		this->m_strUserAgent = rhs.m_strUserAgent;
	}
	return *this;
}
bool CSIPUserAgent::operator==(const CSIPUserAgent& other) const
{
	if(this->m_eType != other.m_eType)
		return false;
	if(this->m_strUserAgent != other.m_strUserAgent)
		return false;
	return true;
}
bool CSIPUserAgent::operator!=(const CSIPUserAgent& other) const
{
	return !(*this == other);
}


CSIPUnknown::CSIPUnknown()
{
	m_eType = CSIPHeader::UNKNOWN;
}

CSIPUnknown::CSIPUnknown(const CSIPUnknown &e)
{
	*this = e;
}
CSIPUnknown::~CSIPUnknown()
{
	Clear();
}
int CSIPUnknown::Parse(const char *pbody,int len)
{
	const char *p = pbody;
	int c = 0;
	while(1)
	{
		if(*p == CR && p[1] == LF)
		{		
			if((p[2] != ' ' && p[2] != HTAB) && c+3 < len)
				return c;
		}
		m_sHeaderValue += *p;
		p++;
		c++;
		if(c >= len)
			return -1;
	}
	return c;
}
mystring CSIPUnknown::Encode()
{
	mystring en;
	en = m_sHeaderName;
	en +=": ";
	en += m_sHeaderValue;
	en += m_Params.Encode();
	return en;
}
mystring CSIPUnknown::EncodeNoName()
{
	mystring en;

	en = m_sHeaderValue;
	en += m_Params.Encode();
	return en;
}
CSIPUnknown& CSIPUnknown::operator=(const CSIPUnknown& rhs)
{
	if(this != &rhs)
	{
		this->m_eType = rhs.m_eType;
		this->m_sHeaderName = rhs.m_sHeaderName;
		this->m_sHeaderValue = rhs.m_sHeaderValue;
		this->m_Params = rhs.m_Params;
	}
	return *this;
}
bool CSIPUnknown::operator==(const CSIPUnknown& other) const
{
	if(this->m_eType != other.m_eType)
		return false;
	if(this->m_sHeaderName != other.m_sHeaderName)
		return false;
	if(this->m_sHeaderValue != other.m_sHeaderValue)
		return false;
	if(this->m_Params != other.m_Params)
		return false;
	return true;
}
bool CSIPUnknown::operator!=(const CSIPUnknown& other) const
{
	return !(*this == other);
}


CSIPRequire::CSIPRequire()
{
	m_eType = CSIPHeader::Require;
}

CSIPRequire::CSIPRequire(const CSIPRequire &e)
{
	*this = e;
}
CSIPRequire::~CSIPRequire()
{
	Clear();
}
int CSIPRequire::Parse(const char *pbody,int len)
{
	const char *p = pbody;
	int c=0;
	while(*p != COMMA)
	{
		if(*p == SP || *p == HTAB || *p == CR || *p == LF || *p == SEMI)
			break;
		
		for(int i=0;i<sizeof(g_Reserved);i++)
		{
			if(*p == g_Reserved[i])
				return -1;
		}
		m_strOptionTag += *p;
		p++;
		c++;
		if(c == len)
		{			
			return c;
		}
	}
	return c;
}
mystring CSIPRequire::Encode()
{
	mystring en;
	en = "Require: ";
	en += m_strOptionTag;
	return en;
}

mystring CSIPRequire::EncodeNoName()
{
	mystring en;
	en = m_strOptionTag;
	return en;
}

CSIPRequire& CSIPRequire::operator=(const CSIPRequire& rhs)
{
	m_strOptionTag = rhs.m_strOptionTag;
	return *this;
}
bool CSIPRequire::operator==(const CSIPRequire& other) const
{
	return m_strOptionTag == other.m_strOptionTag;
}
bool CSIPRequire::operator!=(const CSIPRequire& other) const
{
	return !(*this == other);
}
void CSIPRequire::Clear()
{
	m_strOptionTag.erase();
}


CSIPAllow::CSIPAllow()
{
	m_eType = Allow;
	m_strMethod.erase();
}

CSIPAllow::CSIPAllow(const CSIPAllow &e)
{
	*this = e;
}
CSIPAllow::~CSIPAllow()
{
	Clear();
}
int CSIPAllow::Parse(const char *pbody,int len)
{//Allow = "Allow" HCOLON Method
	const char *p = pbody;
	int c=0;
	Clear();
	while(*p != COMMA)
	{
		if(*p == SP || *p == HTAB || *p == CR || *p == LF || *p == SEMI)
			break;
		
		for(int i=0;i<sizeof(g_Reserved);i++)
		{
			if(*p == g_Reserved[i])
				return -1;
		}
		m_strMethod += *p;
		p++;
		c++;
		if(c == len)
		{		
			return c;
		}
	}
	return c;
}
mystring CSIPAllow::Encode()
{
	mystring en;
	en = "Allow: ";
	en += m_strMethod;
	return en;
}
mystring CSIPAllow::EncodeNoName()
{
	mystring en;
	en = m_strMethod;
	return en;
}
CSIPAllow& CSIPAllow::operator=(const CSIPAllow& rhs)
{
	if(this != &rhs)
	{
		Clear();
		m_strMethod = rhs.m_strMethod;
	}
	return *this;
}
bool CSIPAllow::operator==(const CSIPAllow& other) const
{
	if(this->m_eType != other.m_eType)
		return false;
	if(this->m_strMethod != other.m_strMethod)
		return false;
	
	return true;
}
bool CSIPAllow::operator!=(const CSIPAllow& other) const
{
	return !(*this == other);
}
void CSIPAllow::Clear()
{
	m_strMethod.erase();
}

char CSIPDate::m_sWeekDay[7][4]=
{
	"Mon","Tue","Wed",
    "Thu","Fri","Sat","Sun"
};

char CSIPDate::m_sMonth[12][4] = 
{
	"Jan" , "Feb" , "Mar" , "Apr"
          , "May" , "Jun" , "Jul" , "Aug"
          , "Sep" , "Oct" , "Nov" , "Dec"

};
CSIPDate::CSIPDate()
{
	m_eType = Date;
}

CSIPDate::CSIPDate(const CSIPDate &e)
{
	*this = e;
}
CSIPDate::~CSIPDate()
{
	Clear();
}
int CSIPDate::Parse(const char *pbody,int len)
{
	const char *p = pbody;
	int c1,c=0;
	mystring str;
	int i;
	while(*p != COMMA)
	{
		if(*p == SP || *p == HTAB || *p == CR || *p == LF || *p == SEMI)
			break;
				
		str += *p;
		p++;c++;
		if(c >= len)
			return -1;
	}

	for(i=0;i<7;i++)
	{
		if(mystricmp(str.c_str(),m_sWeekDay[i]) == 0)
		{
			m_nWeekDay = i;
			break;
		}
	}
	if(i >= 7)
		return -1;
	SKIPLWS(p,len,c,c1);
	str.erase();
	while(*p != SP)
	{
		if(*p == SP || *p == HTAB || *p == CR || *p == LF || *p == SEMI)
			break;	
		
		str += *p;
		p++;c++;
		if(c >= len)
			return -1;
	}
	m_nMDay = atoi(str.c_str());
	if(m_nMDay <= 0)
		return -1;
	SKIPLWS(p,len,c,c1);
	str.erase();
	while(*p != SP)
	{
		if(*p == SP || *p == HTAB || *p == CR || *p == LF || *p == SEMI)
			break;		
		str += *p;
		p++;c++;
		if(c >= len)
			return -1;
	}
	for(i=0;i<12;i++)
	{
		if(mystricmp(str.c_str(),m_sMonth[i]) == 0)
		{
			m_nMonth = i;
			break;
		}
	}
	if(i >= 12)
		return -1;
	SKIPLWS(p,len,c,c1);
	str.erase();
	while(*p != SP)
	{
		if(*p == SP || *p == HTAB || *p == CR || *p == LF || *p == SEMI)
			break;		
		
		str += *p;
		p++;c++;
		if(c >= len)
			return -1;
	}
	m_nYear = atoi(str.c_str());
	if(m_nYear <= 0)
		return -1;
	//time 
	SKIPLWS(p,len,c,c1);
	str.erase();
	str += *p;
	p++;c++;
	str += *p;
	p++;c++;
	if(*p != ':')
		return -1;	
	m_nHour = atoi(str.c_str());
	
	str.erase();
	str += *p;
	p++;c++;
	str += *p;
	p++;c++;
	if(*p != ':')
		return -1;	
	m_nMinute = atoi(str.c_str());

	str.erase();
	str += *p;
	p++;c++;
	str += *p;
	p++;c++;
	if(*p != SP)
		return -1;	
	m_nSecond = atoi(str.c_str());

	str.erase();
	str += *p;
	p++,c++;
	str += *p;
	p++,c++;
	str += *p;
	p++,c++;
	if(str != "GMT")
		return -1;
	return c;	
}
mystring CSIPDate::Encode()
{//Date          =  "Date" HCOLON SIP-date
//SIP-date      =  rfc1123-date
//rfc1123-date  =  wkday "," SP date1 SP time SP "GMT"
//date1         =  2DIGIT SP month SP 4DIGIT
//                 ; day month year (e.g., 02 Jun 1982)
//time          =  2DIGIT ":" 2DIGIT ":" 2DIGIT
//                 ; 00:00:00 - 23:59:59
//wkday         =  "Mon" / "Tue" / "Wed"
//                 / "Thu" / "Fri" / "Sat" / "Sun"
//month         =  "Jan" / "Feb" / "Mar" / "Apr"
//                 / "May" / "Jun" / "Jul" / "Aug"
//                / "Sep" / "Oct" / "Nov" / "Dec"

	mystring en;
	
	char buf[64];
	sprintf(buf,"Date: %s, %02d %s %04d %02d:%02d:%02d GMT",
		m_sWeekDay[m_nWeekDay],m_nMDay +1, m_sMonth[m_nMonth],m_nYear,
		m_nHour,m_nMinute,m_nSecond);
	en = buf;
	return en;
}
mystring CSIPDate::EncodeNoName()
{//Date          =  "Date" HCOLON SIP-date
//SIP-date      =  rfc1123-date
//rfc1123-date  =  wkday "," SP date1 SP time SP "GMT"
//date1         =  2DIGIT SP month SP 4DIGIT
//                 ; day month year (e.g., 02 Jun 1982)
//time          =  2DIGIT ":" 2DIGIT ":" 2DIGIT
//                 ; 00:00:00 - 23:59:59
//wkday         =  "Mon" / "Tue" / "Wed"
//                 / "Thu" / "Fri" / "Sat" / "Sun"
//month         =  "Jan" / "Feb" / "Mar" / "Apr"
//                 / "May" / "Jun" / "Jul" / "Aug"
//                / "Sep" / "Oct" / "Nov" / "Dec"

	mystring en;
	
	char buf[64];
	sprintf(buf,"%s, %02d %s %04d %02d:%02d:%02d GMT",
		m_sWeekDay[m_nWeekDay],m_nMDay +1, m_sMonth[m_nMonth],m_nYear,
		m_nHour,m_nMinute,m_nSecond);
	en = buf;
	return en;
}
CSIPDate& CSIPDate::operator=(const CSIPDate& rhs)
{
	if(this != &rhs)
	{
		Clear();
		m_nYear =rhs.m_nYear;
		m_nMonth = rhs.m_nMonth;
		m_nMDay = rhs.m_nMDay;
		m_nHour = rhs.m_nHour;
		m_nMinute = rhs.m_nMinute;
		m_nSecond = rhs.m_nSecond;
		m_nWeekDay = rhs.m_nWeekDay;
	}
	return *this;
}
bool CSIPDate::operator==(const CSIPDate& rhs) const
{
	if(m_nYear != rhs.m_nYear)
		return false;
	if(m_nMonth != rhs.m_nMonth)
		return false;
	if(m_nMDay != rhs.m_nMDay)
		return false;
	if(m_nHour != rhs.m_nHour)
		return false;
	if(m_nMinute != rhs.m_nMinute)
		return false;
	if(m_nSecond != rhs.m_nSecond)
		return false;
	if(m_nWeekDay != rhs.m_nWeekDay)
		return false;
	return true;
}
bool CSIPDate::operator!=(const CSIPDate& other) const
{
	return !(*this == other);
}
void CSIPDate::Clear()
{
	m_nYear = 0;
	m_nMonth = 0;
	m_nMDay = 0;
	m_nHour = 0;
	m_nMinute = 0;
	m_nSecond = 0;
	m_nWeekDay = 0;
}



CSIPRoute::CSIPRoute()
{
	
}

CSIPRoute::CSIPRoute(const CSIPRoute &e)
{
	*this = e;
}
CSIPRoute::~CSIPRoute()
{
	Clear();
}
int CSIPRoute::Parse(const char *pbody,int len)
{
	const char *p = pbody;
	int c1 ,c = 0;	
	c1 = m_NameAddr.Parse(p,len);
	if(c1 == -1)
		return -1;
	p+=c1;
	c+=c1;
	SKIPLWS(p,len,c,c1);
	while(*p == SEMI)
	{
		p++;c++;
		SKIPLWS(p,len,c,c1);
		c1 = m_Params.ParseVIAParams(p,len - c);
		if(c1 == -1)
			return -1;
		p+=c1;
		c+=c1;
		SKIPLWS(p,len,c,c1);
	}	
	return c;	
}
mystring CSIPRoute::Encode()
{
	mystring en;
	if(m_eType == CSIPHeader::Route)
		en = "Route: ";
	else if(m_eType == CSIPHeader::RecordRoute)
		en = "Record-Route: ";
	else
		return en;
	en += m_NameAddr.Encode();
	en += m_Params.Encode();
	return en;
}

mystring CSIPRoute::EncodeNoName()
{
	mystring en;
	en = m_NameAddr.Encode();
	en += m_Params.Encode();
	return en;
}
CSIPRoute& CSIPRoute::operator=(const CSIPRoute& rhs)
{
	Clear();
	m_NameAddr = rhs.m_NameAddr;
	m_Params = rhs.m_Params;	
	return *this;
}
bool CSIPRoute::operator==(const CSIPRoute& other) const
{
	if(this->m_eType != other.m_eType)
		return false;
	if(this->m_NameAddr != other.m_NameAddr)
		return false;	
	return true;
}
bool CSIPRoute::operator!=(const CSIPRoute& other) const
{
	return !(*this == other);
}
void CSIPRoute::Clear()
{	
	m_NameAddr.Clear();
	m_Params.Clear();
}


CSIPAuthorization::CSIPAuthorization()
{
	
}

CSIPAuthorization::CSIPAuthorization(const CSIPAuthorization &e)
{
	*this = e;
}
CSIPAuthorization::~CSIPAuthorization()
{
	Clear();
}
int CSIPAuthorization::Parse(const char *pbody,int len)
{
	const char *p = pbody;
	int c1 ,c = 0;	
	mystring digest;
	mystring name,value;
	Clear();
	while(*p != COMMA)
	{
		if(*p == SP || *p == HTAB || *p == CR || *p == LF)
			break;
				
		digest += *p;
		p++;c++;
		if(c >= len)
			return -1;
	}	
	SKIPLWS(p,len,c,c1);

	while(1)
	{
		name.erase();
		value.erase();		
		SKIPLWS(p,len,c,c1);
		while(*p != '=')
		{
			if(*p == SP || *p == HTAB || *p == CR || *p == LF)
				break;
			name += *p;
			p++;c++;
			if(c >= len)
				return -1;
		}		
		SKIPLWS(p,len,c,c1);
		if(*p != '=')
			return -1;

		p++;
		c++;
		SKIPLWS(p,len,c,c1);
		if(*p != DQUOTE)
		{
			while(*p != COMMA)
			{
				if(*p == SP || *p == HTAB || *p == CR || *p == LF)
					break;
				value += *p;
				p++;c++;
				if(c >= len)
					return -1;
			}
		}
		else
		{
			p++;
			c++;
			SKIPLWS(p,len,c,c1);
			while(*p != DQUOTE)
			{			
				value += *p;
				p++;c++;
				if(c >= len)
					return -1;
			}
			p++;
			c++;
		}		
		SKIPLWS(p,len,c,c1);
		if(name == "username")
			m_strUserName = value;
		else if(name == "uri")
			m_strDigestUri = value;
		else if(name == "qop")
			m_strQop = value;
		else if(name == "cnonce")
			m_strCNonce = value;
		else if(name == "nonce")
			m_strNonce = value;
		else if(name == "realm")
			m_strRealm = value;
		else if(name == "nc")
			m_strNonceCount = value;
		else if(name == "response")
			m_strResponse = value;
		else if(name == "opaque")
			m_strOpaque = value;
		else if(name == "algorithm")
			m_strAlgorithm = value;
		if(*p != COMMA)
			break;
		p++;c++;
	}
	return c;	
}
mystring CSIPAuthorization::Encode()
{
	mystring en;
	bool comma = false;
	en = "Authorization: Digest ";
	if(m_strUserName.empty() == false)
	{
		en += "username=\"" + m_strUserName + "\"";
		comma = true;
	}
	if(m_strRealm.empty() == false)
	{
		if(comma)
			en += ",realm=\"" + m_strRealm + "\"";
		else
		{
			en += "realm=\"" + m_strRealm + "\"";
			comma = true;
		}
	}
	if(m_strNonce.empty() == false)
	{
		if(comma)
			en += ",nonce=\"" + m_strNonce + "\"";
		else
		{
			en += "nonce=\"" + m_strNonce + "\"";
			comma = true;
		}
	}
	if(m_strDigestUri.empty() == false)
	{
		if(comma)
			en += ",uri=\"" + m_strDigestUri + "\"";
		else
		{
			en += "uri=\"" + m_strDigestUri + "\"";
			comma = true;
		}
	}
	if(m_strQop.empty() == false)
	{
		if(comma)
			en += ",qop=\"" + m_strQop + "\"";
		else
		{
			en += "qop=\"" + m_strQop + "\"";
			comma = true;
		}
	}
	if(m_strCNonce.empty() == false)
	{
		if(comma)
			en += ",cnonce=\"" + m_strCNonce + "\"";
		else
		{
			en += "cnonce=\"" + m_strCNonce + "\"";
			comma = true;
		}
	}
	if(m_strNonceCount.empty() == false)
	{
		if(comma)
			en += ",nc=\"" + m_strNonceCount + "\"";
		else
		{
			en += "nc=\"" + m_strNonceCount + "\"";
			comma = true;
		}
	}
	if(m_strResponse.empty() == false)
	{
		if(comma)
			en += ",response=\"" + m_strResponse + "\"";
		else
		{
			en += "response=\"" + m_strResponse + "\"";
			comma = true;
		}
	}
	if(m_strOpaque.empty() == false)
	{
		if(comma)
			en += ",opaque=\"" + m_strOpaque + "\"";
		else
		{
			en += "opaque=\"" + m_strOpaque + "\"";
			comma = true;
		}
	}
	return en;
}

mystring CSIPAuthorization::EncodeNoName()
{
	mystring en;
	bool comma = false;	
	en = "Digest ";
	if(m_strUserName.empty() == false)
	{
		en += "username='\"" + m_strUserName + "\"";
		comma = true;
	}
	if(m_strRealm.empty() == false)
	{
		if(comma)
			en += ",realm=\"" + m_strRealm + "\"";
		else
		{
			en += "realm=\"" + m_strRealm + "\"";
			comma = true;
		}
	}
	if(m_strNonce.empty() == false)
	{
		if(comma)
			en += ",nonce=\"" + m_strNonce + "\"";
		else
		{
			en += "nonce=\"" + m_strNonce + "\"";
			comma = true;
		}
	}
	if(m_strDigestUri.empty() == false)
	{
		if(comma)
			en += ",uri=\"" + m_strDigestUri + "\"";
		else
		{
			en += "uri=\"" + m_strDigestUri + "\"";
			comma = true;
		}
	}
	if(m_strQop.empty() == false)
	{
		if(comma)
			en += ",qop=\"" + m_strQop + "\"";
		else
		{
			en += "qop=\"" + m_strQop + "\"";
			comma = true;
		}
	}
	if(m_strCNonce.empty() == false)
	{
		if(comma)
			en += ",cnonce=\"" + m_strCNonce + "\"";
		else
		{
			en += "cnonce=\"" + m_strCNonce + "\"";
			comma = true;
		}
	}
	if(m_strNonceCount.empty() == false)
	{
		if(comma)
			en += ",nc=\"" + m_strNonceCount + "\"";
		else
		{
			en += "nc=\"" + m_strNonceCount + "\"";
			comma = true;
		}
	}
	if(m_strResponse.empty() == false)
	{
		if(comma)
			en += ",response=\"" + m_strResponse + "\"";
		else
		{
			en += "response=\"" + m_strResponse + "\"";
			comma = true;
		}
	}
	if(m_strOpaque.empty() == false)
	{
		if(comma)
			en += ",opaque=\"" + m_strOpaque + "\"";
		else
		{
			en += "opaque=\"" + m_strOpaque + "\"";
			comma = true;
		}
	}
	return en;
}
CSIPAuthorization& CSIPAuthorization::operator=(const CSIPAuthorization& rhs)
{
	Clear();
	m_strUserName = rhs.m_strUserName;
	m_strDigestUri = rhs.m_strDigestUri;
	m_strQop = rhs.m_strQop;
	m_strCNonce = rhs.m_strCNonce;
	m_strNonceCount = rhs.m_strNonceCount;
	m_strResponse = rhs.m_strResponse;
	m_strRealm = rhs.m_strRealm;
	m_strNonce = rhs.m_strNonce;
	m_strOpaque = rhs.m_strOpaque;
	return *this;
}
bool CSIPAuthorization::operator==(const CSIPAuthorization& other) const
{	
	if(m_strUserName != other.m_strUserName)
		return false;
	if(m_strDigestUri != other.m_strDigestUri)
		return false;
	if(m_strQop != other.m_strQop)
		return false;
	if(m_strCNonce != other.m_strCNonce)
		return false;
	if(m_strNonceCount != other.m_strNonceCount)
		return false;
	if(m_strResponse != other.m_strResponse)
		return false;
	if(m_strRealm != other.m_strRealm)
		return false;
	if(m_strNonce != other.m_strNonce)
		return false;
	if(m_strOpaque != other.m_strOpaque)
		return false;
	return true;
}
bool CSIPAuthorization::operator!=(const CSIPAuthorization& other) const
{
	return !(*this == other);
}
void CSIPAuthorization::Clear()
{	
	m_strUserName.erase();
	m_strDigestUri.erase();
	m_strQop.erase();
	m_strCNonce.erase();
	m_strNonceCount.erase();
	m_strResponse.erase();
	m_strRealm.erase();
	m_strNonce.erase();
	m_strOpaque.erase();
}



CSIPWWWAuthenticate::CSIPWWWAuthenticate()
{
	
}

CSIPWWWAuthenticate::CSIPWWWAuthenticate(const CSIPWWWAuthenticate &e)
{
	*this = e;
}
CSIPWWWAuthenticate::~CSIPWWWAuthenticate()
{
	Clear();
}
int CSIPWWWAuthenticate::Parse(const char *pbody,int len)
{
	const char *p = pbody;
	int c1 ,c = 0;	
	mystring digest;
	mystring name,value;
	Clear();
	while(1)
	{
		if(*p == SP || *p == HTAB || *p == CR || *p == LF)
			break;
				
		digest += *p;
		p++;c++;
		if(c >= len)
			return -1;
	}	
	SKIPLWS(p,len,c,c1);

	while(1)
	{
		name.erase();
		value.erase();
		SKIPLWS(p,len,c,c1);
		while(*p != '=')
		{
			if(*p == SP || *p == HTAB || *p == CR || *p == LF)
				break;				
			name += *p;
			p++;c++;
			if(c >= len)
				return -1;
		}		
		SKIPLWS(p,len,c,c1);
		if(*p != '=')
			return -1;

		p++;
		c++;
		SKIPLWS(p,len,c,c1);		
		if(*p != DQUOTE)
		{
			while(*p != COMMA)
			{
				if(*p == SP || *p == HTAB || *p == CR || *p == LF)
					break;
				value += *p;
				p++;c++;
				if(c >= len)
					return -1;
			}
		}
		else
		{
			p++;
			c++;
			SKIPLWS(p,len,c,c1);
			while(*p != DQUOTE)
			{			
				value += *p;
				p++;c++;
				if(c >= len)
					return -1;
			}
			p++;
			c++;
		}	
		SKIPLWS(p,len,c,c1);
	
		if(name == "domain")
			m_strDomain = value;
		else if(name == "opaque")
			m_strOpaque = value;
		else if(name == "qop")
			m_strQop = value;
		else if(name == "nonce")
			m_strNonce = value;
		else if(name == "stale")
			m_strStale = value;
		else if(name == "algorithm")
			m_strAlgorithm = value;
		else if(name == "realm")
			m_strRealm = value;
		if(*p != COMMA)
			break;
		p++;
		c++;
	}
	return c;	
}
mystring CSIPWWWAuthenticate::Encode()
{
	mystring en;
	bool comma = false;
	en = "WWW-Authenticate: Digest ";
	if(m_strRealm.empty() == false)
	{
		en += "realm=\"" + m_strRealm + "\"";
		comma = true;
	}
	if(m_strDomain.empty() == false)
	{
		if(comma)
			en += ",domain=\"" + m_strDomain + "\"";
		else
		{
			en += "dommain=\"" + m_strDomain + "\"";
			comma = true;
		}
	}
	if(m_strQop.empty() == false)
	{
		if(comma)
			en += ",qop=\"" + m_strQop + "\"";
		else
		{
			en += "qop=\"" + m_strQop + "\"";
			comma = true;
		}
	}
	if(m_strNonce.empty() == false)
	{
		if(comma)
			en += ",nonce=\"" + m_strNonce + "\"";
		else
		{
			en += "nonce=\"" + m_strNonce + "\"";
			comma = true;
		}
	}
	if(m_strAlgorithm.empty() == false)
	{
		if(comma)
			en += ",algorithm=\"" + m_strAlgorithm + "\"";
		else
		{
			en += "nonce=\"" + m_strAlgorithm + "\"";
			comma = true;
		}
	}
	if(m_strOpaque.empty() == false)
	{
		if(comma)
			en += ",opaque=\"" + m_strOpaque + "\"";
		else
		{
			en += "opaque=\"" + m_strOpaque + "\"";
			comma = true;
		}
	}
	if(m_strStale.empty() == false)
	{
		if(comma)
			en += ",stale=\"" + m_strStale + "\"";
		else
		{
			en += "stale=\"" + m_strStale + "\"";
			comma = true;
		}
	}
	return en;
}

mystring CSIPWWWAuthenticate::EncodeNoName()
{
	mystring en;
	bool comma = false;
	en = "Digest ";
	if(m_strRealm.empty() == false)
	{
		en += "realm='\"" + m_strRealm + "\"";
		comma = true;
	}
	if(m_strDomain.empty() == false)
	{
		if(comma)
			en += ",domain=\"" + m_strDomain + "\"";
		else
		{
			en += "dommain=\"" + m_strDomain + "\"";
			comma = true;
		}
	}
	if(m_strQop.empty() == false)
	{
		if(comma)
			en += ",qop=\"" + m_strQop + "\"";
		else
		{
			en += "qop=\"" + m_strQop + "\"";
			comma = true;
		}
	}
	if(m_strNonce.empty() == false)
	{
		if(comma)
			en += ",nonce=\"" + m_strNonce + "\"";
		else
		{
			en += "nonce=\"" + m_strNonce + "\"";
			comma = true;
		}
	}
	if(m_strAlgorithm.empty() == false)
	{
		if(comma)
			en += ",algorithm=\"" + m_strAlgorithm + "\"";
		else
		{
			en += "nonce=\"" + m_strAlgorithm + "\"";
			comma = true;
		}
	}
	if(m_strOpaque.empty() == false)
	{
		if(comma)
			en += ",opaque=\"" + m_strOpaque + "\"";
		else
		{
			en += "opaque=\"" + m_strOpaque + "\"";
			comma = true;
		}
	}
	if(m_strStale.empty() == false)
	{
		if(comma)
			en += ",stale=\"" + m_strStale + "\"";
		else
		{
			en += "stale=\"" + m_strStale + "\"";
			comma = true;
		}
	}
	return en;
}

CSIPWWWAuthenticate& CSIPWWWAuthenticate::operator=(const CSIPWWWAuthenticate& rhs)
{
	Clear();
	m_strDomain = rhs.m_strDomain;
	m_strAlgorithm = rhs.m_strAlgorithm;
	m_strQop = rhs.m_strQop;
	m_strNonce = rhs.m_strNonce;
	m_strRealm = rhs.m_strRealm;
	m_strStale = rhs.m_strStale;
	m_strOpaque = rhs.m_strOpaque;
	return *this;
}
bool CSIPWWWAuthenticate::operator==(const CSIPWWWAuthenticate& other) const
{	
	if(m_strDomain != other.m_strDomain)
		return false;
	if(m_strAlgorithm != other.m_strAlgorithm)
		return false;
	if(m_strQop != other.m_strQop)
		return false;
	if(m_strNonce != other.m_strNonce)
		return false;
	if(m_strRealm != other.m_strRealm)
		return false;
	if(m_strStale != other.m_strStale)
		return false;
	if(m_strOpaque != other.m_strOpaque)
		return false;
	return true;
}
bool CSIPWWWAuthenticate::operator!=(const CSIPWWWAuthenticate& other) const
{
	return !(*this == other);
}
void CSIPWWWAuthenticate::Clear()
{	
	m_strDomain.erase();
	m_strAlgorithm.erase();
	m_strQop.erase();
	m_strNonce.erase();
	m_strRealm.erase();
	m_strStale.erase();
	m_strOpaque.erase();
}



CSIPMIMEVersion::CSIPMIMEVersion()
{
	
}

CSIPMIMEVersion::CSIPMIMEVersion(const CSIPMIMEVersion &e)
{
	*this = e;
}
CSIPMIMEVersion::~CSIPMIMEVersion()
{
	Clear();
}
int CSIPMIMEVersion::Parse(const char *pbody,int len)
{
	const char *p = pbody;
	int c = 0;	
	Clear();
	while(1)
	{
		if(isDIGIT(*p) || *p == '.')
			m_strVersion += *p;
		else
			break;
		p++;c++;
		if(c >= len)
			break;
	}
	return c;	
}
mystring CSIPMIMEVersion::Encode()
{
	mystring en;
	en = "MIME-Version: ";
	en += m_strVersion;
	return en;
}

mystring CSIPMIMEVersion::EncodeNoName()
{
	mystring en;
	en = m_strVersion;
	return en;
}

CSIPMIMEVersion& CSIPMIMEVersion::operator=(const CSIPMIMEVersion& rhs)
{
	Clear();
	this->m_strVersion = rhs.m_strVersion;
	return *this;
}
bool CSIPMIMEVersion::operator==(const CSIPMIMEVersion& other) const
{	
	if(m_strVersion != other.m_strVersion)
		return false;

	return true;
}
bool CSIPMIMEVersion::operator!=(const CSIPMIMEVersion& other) const
{
	return !(*this == other);
}
void CSIPMIMEVersion::Clear()
{	
	m_strVersion.erase();
}



CSIPAcceptEncoding::CSIPAcceptEncoding()
{
	
}

CSIPAcceptEncoding::CSIPAcceptEncoding(const CSIPAcceptEncoding &e)
{
	*this = e;
}
CSIPAcceptEncoding::~CSIPAcceptEncoding()
{
	Clear();
}
int CSIPAcceptEncoding::Parse(const char *pbody,int len)
{
	const char *p = pbody;
	int c = 0,c1;	
	Clear();
	while(*p != SEMI)
	{
		if(istoken(*p))
			m_strCodings += *p;
		else
			break;
		p++;c++;
		if(c >= len)
			return -1;
	}
	SKIPLWS(p,len,c,c1);
	while(*p == SEMI)
	{
		p++;c++;
		SKIPLWS(p,len,c,c1);
		c1 = m_Params.ParseVIAParams(p,len - c);
		if(c1 == -1)
			return -1;
		p+=c1;
		c+=c1;
		SKIPLWS(p,len,c,c1);
	}
	return c;	
}
mystring CSIPAcceptEncoding::Encode()
{
	mystring en;
	en = "Accept-Encoding: ";
	en += m_strCodings;
	en += m_Params.Encode();
	return en;
}

mystring CSIPAcceptEncoding::EncodeNoName()
{
	mystring en;
	en = m_strCodings;
	en += m_Params.Encode();
	return en;
}

CSIPAcceptEncoding& CSIPAcceptEncoding::operator=(const CSIPAcceptEncoding& rhs)
{
	Clear();
	this->m_strCodings = rhs.m_strCodings;
	this->m_Params = rhs.m_Params;
	return *this;
}
bool CSIPAcceptEncoding::operator==(const CSIPAcceptEncoding& other) const
{
	if(m_strCodings != other.m_strCodings)
		return false;
	if(m_Params != other.m_Params)
		return false;
	return true;
}
bool CSIPAcceptEncoding::operator!=(const CSIPAcceptEncoding& other) const
{
	return !(*this == other);
}
void CSIPAcceptEncoding::Clear()
{	
	m_strCodings.erase();
	m_Params.Clear();
}



CSIPAcceptLanguage::CSIPAcceptLanguage()
{
	
}

CSIPAcceptLanguage::CSIPAcceptLanguage(const CSIPAcceptLanguage &e)
{
	*this = e;
}
CSIPAcceptLanguage::~CSIPAcceptLanguage()
{
	Clear();
}
int CSIPAcceptLanguage::Parse(const char *pbody,int len)
{
	const char *p = pbody;
	int c = 0,c1;	
	Clear();
	while(*p != SEMI)
	{
		if(isALPHA(*p) || *p == STAR || *p == '-')
			m_strLanguage += *p;
		else
			break;
		p++;c++;
		if(c >= len)
			return -1;
	}
	SKIPLWS(p,len,c,c1);
	while(*p == SEMI)
	{
		p++;c++;
		SKIPLWS(p,len,c,c1);
		c1 = m_Params.ParseVIAParams(p,len - c);
		if(c1 == -1)
			return -1;
		p+=c1;
		c+=c1;
		SKIPLWS(p,len,c,c1);
	}
	return c;	
}
mystring CSIPAcceptLanguage::Encode()
{
	mystring en;
	en = "Accept-Language: ";
	en += m_strLanguage;
	en += m_Params.Encode();
	return en;
}

mystring CSIPAcceptLanguage::EncodeNoName()
{
	mystring en;
	en = m_strLanguage;
	en += m_Params.Encode();
	return en;
}

CSIPAcceptLanguage& CSIPAcceptLanguage::operator=(const CSIPAcceptLanguage& rhs)
{
	Clear();
	this->m_strLanguage = rhs.m_strLanguage;
	this->m_Params = rhs.m_Params;
	return *this;
}
bool CSIPAcceptLanguage::operator==(const CSIPAcceptLanguage& other) const
{
	if(m_strLanguage != other.m_strLanguage)
		return false;
	if(m_Params != other.m_Params)
		return false;
	return true;
}
bool CSIPAcceptLanguage::operator!=(const CSIPAcceptLanguage& other) const
{
	return !(*this == other);
}
void CSIPAcceptLanguage::Clear()
{	
	m_strLanguage.erase();
	m_Params.Clear();
}
//#ifdef PC_CLIENT

CSIPAlertInfo::CSIPAlertInfo()
{
	
}

CSIPAlertInfo::CSIPAlertInfo(const CSIPAlertInfo &e)
{
	*this = e;
}
CSIPAlertInfo::~CSIPAlertInfo()
{
	Clear();
}
int CSIPAlertInfo::Parse(const char *pbody,int len)
{
	const char *p = pbody;
	int c = 0,c1;
	const char *p1;
	Clear();
	while(*p == LAQUOT)
	{
		p++;c++;
		p1 = p;
		c1 = c;
		while(*p1 != RAQUOT)
		{
			p1++;c1++;
			if(c1 >= len)
				return -1;
		}
		if(m_AbsoluteUri.Parse(p,c1 - c) == -1)
			return -1;
		p1++;c1++;
		p = p1;c=c1;
		break;
	}
	SKIPLWS(p,len,c,c1);
	while(*p == SEMI)
	{
		p++;c++;
		SKIPLWS(p,len,c,c1);
		c1 = m_Params.ParseVIAParams(p,len - c);
		if(c1 == -1)
			return -1;
		p+=c1;
		c+=c1;
		SKIPLWS(p,len,c,c1);
	}
	return c;	
}
mystring CSIPAlertInfo::Encode()
{
	mystring en;
	en = "Alert-Info: ";
	en += "\"" + m_AbsoluteUri.Encode() + "\"";
	en += m_Params.Encode();
	return en;
}

mystring CSIPAlertInfo::EncodeNoName()
{
	mystring en;
	en = "\"" + m_AbsoluteUri.Encode() + "\"";
	en += m_Params.Encode();
	return en;
}

CSIPAlertInfo& CSIPAlertInfo::operator=(const CSIPAlertInfo& rhs)
{
	Clear();
	this->m_AbsoluteUri = rhs.m_AbsoluteUri;
	this->m_Params = rhs.m_Params;
	return *this;
}
bool CSIPAlertInfo::operator==(const CSIPAlertInfo& other) const
{
	if(m_AbsoluteUri != other.m_AbsoluteUri)
		return false;
	if(m_Params != other.m_Params)
		return false;
	return true;
}
bool CSIPAlertInfo::operator!=(const CSIPAlertInfo& other) const
{
	return !(*this == other);
}
void CSIPAlertInfo::Clear()
{	
	m_AbsoluteUri.Clear();
	m_Params.Clear();
}



CSIPAuthenticationInfo::CSIPAuthenticationInfo()
{
	
}

CSIPAuthenticationInfo::CSIPAuthenticationInfo(const CSIPAuthenticationInfo &e)
{
	*this = e;
}
CSIPAuthenticationInfo::~CSIPAuthenticationInfo()
{
	Clear();
}
int CSIPAuthenticationInfo::Parse(const char *pbody,int len)
{
	const char *p = pbody;
	int c1 ,c = 0;	
	mystring digest;
	mystring name,value;
	Clear();	
	while(1)
	{
		name.erase();
		value.erase();		
		SKIPLWS(p,len,c,c1);
		while(*p != '=')
		{
			if(*p == SP || *p == HTAB || *p == CR || *p == LF)
				break;				
			name += *p;
			p++;c++;
			if(c >= len)
				return -1;
		}		
		SKIPLWS(p,len,c,c1);
		if(*p != '=')
			return -1;

		p++;
		c++;
		SKIPLWS(p,len,c,c1);		
		if(*p == DQUOTE)
		{			
			p++;
			c++;
			SKIPLWS(p,len,c,c1);
			while(*p != DQUOTE)
			{			
				value += *p;
				p++;c++;
				if(c >= len)
					return -1;
			}
			SKIPLWS(p,len,c,c1);
			p++;
			c++;
		}
		else
		{
			while(*p)
			{			
				if(*p == SP || *p == HTAB || *p == CR || *p == LF)
					break;
				value += *p;
				p++;c++;
				if(c >= len)
					return -1;
			}
		}		
		SKIPLWS(p,len,c,c1);
		if(name == "nextnonce")
			m_strNextNonce = value;
		else if(name == "rspauth")
			m_strResponseAuth = value;
		else if(name == "qop")
			m_strMessageQop = value;
		else if(name == "cnonce")
			m_strCNonce = value;
		else if(name == "nc")
			m_strNonceCount = value;
		if(*p != COMMA)
			break;
		p++;c++;
	}
	return c;	
}
mystring CSIPAuthenticationInfo::Encode()
{
	mystring en;
	bool comma = false;
	en = "Authentication-Info: ";
	if(m_strNextNonce.empty() == false)
	{
		en += "nextnonce='\"" + m_strNextNonce + "\"";
		comma = true;
	}
	if(m_strMessageQop.empty() == false)
	{
		if(comma)
			en += ",qop=\"" + m_strMessageQop + "\"";
		else
		{
			en += "qop=\"" + m_strMessageQop + "\"";
			comma = true;
		}
	}
	if(m_strResponseAuth.empty() == false)
	{
		if(comma)
			en += ",rspauth=\"" + m_strResponseAuth + "\"";
		else
		{
			en += "rspauth=\"" + m_strResponseAuth + "\"";
			comma = true;
		}
	}
	if(m_strCNonce.empty() == false)
	{
		if(comma)
			en += ",cnonce=\"" + m_strCNonce + "\"";
		else
		{
			en += "cnonce=\"" + m_strCNonce + "\"";
			comma = true;
		}
	}
	if(m_strNonceCount.empty() == false)
	{
		if(comma)
			en += ",nc=\"" + m_strNonceCount + "\"";
		else
		{
			en += "nc=\"" + m_strNonceCount + "\"";
			comma = true;
		}
	}	
	return en;
}

mystring CSIPAuthenticationInfo::EncodeNoName()
{
	mystring en;
	bool comma = false;	
	if(m_strNextNonce.empty() == false)
	{
		en += "nextnonce='\"" + m_strNextNonce + "\"";
		comma = true;
	}
	if(m_strMessageQop.empty() == false)
	{
		if(comma)
			en += ",qop=\"" + m_strMessageQop + "\"";
		else
		{
			en += "qop=\"" + m_strMessageQop + "\"";
			comma = true;
		}
	}
	if(m_strResponseAuth.empty() == false)
	{
		if(comma)
			en += ",rspauth=\"" + m_strResponseAuth + "\"";
		else
		{
			en += "rspauth=\"" + m_strResponseAuth + "\"";
			comma = true;
		}
	}
	if(m_strCNonce.empty() == false)
	{
		if(comma)
			en += ",cnonce=\"" + m_strCNonce + "\"";
		else
		{
			en += "cnonce=\"" + m_strCNonce + "\"";
			comma = true;
		}
	}
	if(m_strNonceCount.empty() == false)
	{
		if(comma)
			en += ",nc=\"" + m_strNonceCount + "\"";
		else
		{
			en += "nc=\"" + m_strNonceCount + "\"";
			comma = true;
		}
	}
	return en;
}

CSIPAuthenticationInfo& CSIPAuthenticationInfo::operator=(const CSIPAuthenticationInfo& other)
{
	Clear();
	m_strNextNonce = other.m_strNextNonce;	
	m_strMessageQop = other.m_strMessageQop;	
	m_strResponseAuth = other.m_strResponseAuth;
	m_strCNonce = other.m_strCNonce;
	m_strNonceCount = other.m_strNonceCount;
	return *this;
}
bool CSIPAuthenticationInfo::operator==(const CSIPAuthenticationInfo& other) const
{
	if(m_strNextNonce != other.m_strNextNonce)
		return false;
	if(m_strMessageQop != other.m_strMessageQop)
		return false;
	if(m_strResponseAuth != other.m_strResponseAuth)
		return false;
	if(m_strCNonce != other.m_strCNonce)
		return false;
	if(m_strNonceCount != other.m_strNonceCount)
		return false;

	return true;
}
bool CSIPAuthenticationInfo::operator!=(const CSIPAuthenticationInfo& other) const
{
	return !(*this == other);
}
void CSIPAuthenticationInfo::Clear()
{		
	m_strMessageQop.erase();
	m_strNextNonce.erase();
	m_strResponseAuth.erase();
	m_strCNonce.erase();
	m_strNonceCount.erase();
	m_Params.Clear();
}


CSIPCallInfo::CSIPCallInfo()
{
	
}

CSIPCallInfo::CSIPCallInfo(const CSIPCallInfo &e)
{
	*this = e;
}
CSIPCallInfo::~CSIPCallInfo()
{
	Clear();
}
int CSIPCallInfo::Parse(const char *pbody,int len)
{
	const char *p = pbody;
	int c = 0,c1;
	const char *p1;
	Clear();
	while(*p == LAQUOT)
	{
		p++;c++;
		p1 = p;
		c1 = c;
		while(*p1 != RAQUOT)
		{
			p1++;c1++;
			if(c1 >= len)
				return -1;
		}
		if(m_AbsoluteUri.Parse(p,c1 - c) == -1)
			return -1;
		p1++;c1++;
		p = p1;c=c1;
		break;
	}
	SKIPLWS(p,len,c,c1);
	while(*p == SEMI)
	{
		p++;c++;
		SKIPLWS(p,len,c,c1);
		c1 = m_Params.ParseVIAParams(p,len - c);
		if(c1 == -1)
			return -1;
		p+=c1;
		c+=c1;
		SKIPLWS(p,len,c,c1);
	}
	return c;	
}
mystring CSIPCallInfo::Encode()
{
	mystring en;
	//en = "Alert-Info: "; // Modified by liuhf 2007.10.10
	en = "Call-Info: "; // Modified by liuhf 2007.10.10
	en += "\"" + m_AbsoluteUri.Encode() + "\"";
	en += m_Params.Encode();
	return en;
}

mystring CSIPCallInfo::EncodeNoName()
{
	mystring en;
	en = "<" + m_AbsoluteUri.Encode() + ">";
	en += m_Params.Encode();
	return en;
}

CSIPCallInfo& CSIPCallInfo::operator=(const CSIPCallInfo& rhs)
{
	Clear();
	this->m_AbsoluteUri = rhs.m_AbsoluteUri;
	this->m_Params = rhs.m_Params;
	return *this;
}
bool CSIPCallInfo::operator==(const CSIPCallInfo& other) const
{
	if(m_AbsoluteUri != other.m_AbsoluteUri)
		return false;
	if(m_Params != other.m_Params)
		return false;
	return true;
}
bool CSIPCallInfo::operator!=(const CSIPCallInfo& other) const
{
	return !(*this == other);
}
void CSIPCallInfo::Clear()
{	
	m_AbsoluteUri.Clear();
	m_Params.Clear();
}



CSIPErrorInfo::CSIPErrorInfo()
{
	
}

CSIPErrorInfo::CSIPErrorInfo(const CSIPErrorInfo &e)
{
	*this = e;
}
CSIPErrorInfo::~CSIPErrorInfo()
{
	Clear();
}
int CSIPErrorInfo::Parse(const char *pbody,int len)
{
	const char *p = pbody;
	int c = 0,c1;
	const char *p1;
	Clear();
	while(*p == LAQUOT)
	{
		p++;c++;
		p1 = p;
		c1 = c;
		while(*p1 != RAQUOT)
		{
			p1++;c1++;
			if(c1 >= len)
				return -1;
		}
		if(m_AbsoluteUri.Parse(p,c1 - c) == -1)
			return -1;
		p1++;c1++;
		p = p1;c=c1;
		break;
	}
	SKIPLWS(p,len,c,c1);
	while(*p == SEMI)
	{
		p++;c++;
		SKIPLWS(p,len,c,c1);
		c1 = m_Params.ParseVIAParams(p,len - c);
		if(c1 == -1)
			return -1;
		p+=c1;
		c+=c1;
		SKIPLWS(p,len,c,c1);
	}
	return c;	
}
mystring CSIPErrorInfo::Encode()
{
	mystring en;
	en = "Alert-Info: ";
	en += "\"" + m_AbsoluteUri.Encode() + "\"";
	en += m_Params.Encode();
	return en;
}

mystring CSIPErrorInfo::EncodeNoName()
{
	mystring en;
	en = "\"" + m_AbsoluteUri.Encode() + "\"";
	en += m_Params.Encode();
	return en;
}

CSIPErrorInfo& CSIPErrorInfo::operator=(const CSIPErrorInfo& rhs)
{
	Clear();
	this->m_AbsoluteUri = rhs.m_AbsoluteUri;
	this->m_Params = rhs.m_Params;
	return *this;
}
bool CSIPErrorInfo::operator==(const CSIPErrorInfo& other) const
{
	if(m_AbsoluteUri != other.m_AbsoluteUri)
		return false;
	if(m_Params != other.m_Params)
		return false;
	return true;
}
bool CSIPErrorInfo::operator!=(const CSIPErrorInfo& other) const
{
	return !(*this == other);
}
void CSIPErrorInfo::Clear()
{	
	m_AbsoluteUri.Clear();
	m_Params.Clear();
}


CSIPInReplyTo::CSIPInReplyTo()
{
	
}

CSIPInReplyTo::CSIPInReplyTo(const CSIPInReplyTo &e)
{
	*this = e;
}
CSIPInReplyTo::~CSIPInReplyTo()
{
	Clear();
}
int CSIPInReplyTo::Parse(const char *pbody,int len)
{
	const char *p = pbody;
	int c = 0;	
	Clear();
	while(*p)
	{
		if(isword(*p) || *p == '@')
			m_strCallID += *p;
		else
			break;
		p++;c++;
		if(c >= len)
			return -1;
	}
	return c;	
}
mystring CSIPInReplyTo::Encode()
{
	mystring en;
	en = "In-Reply-To: ";
	en += m_strCallID;	
	return en;
}

mystring CSIPInReplyTo::EncodeNoName()
{
	mystring en;
	en = m_strCallID;
	return en;
}

CSIPInReplyTo& CSIPInReplyTo::operator=(const CSIPInReplyTo& rhs)
{
	Clear();
	this->m_strCallID = rhs.m_strCallID;
	return *this;
}
bool CSIPInReplyTo::operator==(const CSIPInReplyTo& other) const
{
	if(m_strCallID != other.m_strCallID)
		return false;	
	return true;
}
bool CSIPInReplyTo::operator!=(const CSIPInReplyTo& other) const
{
	return !(*this == other);
}
void CSIPInReplyTo::Clear()
{	
	m_strCallID.erase();	
}



CSIPOrganization::CSIPOrganization()
{
	
}

CSIPOrganization::CSIPOrganization(const CSIPOrganization &e)
{
	*this = e;
}
CSIPOrganization::~CSIPOrganization()
{
	Clear();
}
int CSIPOrganization::Parse(const char *pbody,int len)
{
	const char *p = pbody;
	int c = 0,c1,c2;	
	Clear();
	while(*p)
	{
		if(*p == CR || *p == LF)
			break;
		m_strOrganization += *p;
		p++;c++;
		c2 = c;
		SKIPLWS(p,len,c,c1);
		if(c > c2)
			m_strOrganization += " ";
		if(c >= len)
			return -1;
	}
	return c;	
}
mystring CSIPOrganization::Encode()
{
	mystring en;
	en = "Organization: ";
	en += m_strOrganization;	
	return en;
}

mystring CSIPOrganization::EncodeNoName()
{
	mystring en;
	en = m_strOrganization;
	return en;
}

CSIPOrganization& CSIPOrganization::operator=(const CSIPOrganization& rhs)
{
	Clear();
	this->m_strOrganization = rhs.m_strOrganization;
	return *this;
}
bool CSIPOrganization::operator==(const CSIPOrganization& other) const
{
	if(m_strOrganization != other.m_strOrganization)
		return false;	
	return true;
}
bool CSIPOrganization::operator!=(const CSIPOrganization& other) const
{
	return !(*this == other);
}
void CSIPOrganization::Clear()
{	
	m_strOrganization.erase();	
}


CSIPReplyTo::CSIPReplyTo():m_NameAddr()
{
}
CSIPReplyTo::CSIPReplyTo(const CSIPReplyTo &addr)
{	
	*this = addr;
}
CSIPReplyTo::~CSIPReplyTo()
{
	Clear();
}
void CSIPReplyTo::SetDisplayName(const char *pname)
{	
	m_NameAddr.SetDisplayName(pname);
}


void CSIPReplyTo::Clear()
{
	m_NameAddr.Clear();
}

int CSIPReplyTo::Parse(const char *pbody,int len)
{//name-addr = [display-name]LAQUOT addr-spec RAQUOT
//addr-spec = SIP-URI/SIPS-URI/absoluteRUI
//display-name = *(token LWS)/quoted-mystring
	Clear();
	int c = 0,c1;
	const char *p = pbody;
	c = m_NameAddr.Parse(p,len);
	if(c == -1)
		return -1;
	p+=c;
	SKIPLWS(p,len,c,c1);
	while(*p == SEMI)
	{
		p++;c++;
		SKIPLWS(p,len,c,c1);
		c1 = m_Params.ParseVIAParams(p,len - c);
		if(c1 == -1)
			return -1;
		p+=c1;
		c+=c1;
		SKIPLWS(p,len,c,c1);
	}
	return c;
}
mystring CSIPReplyTo::Encode()
{
	mystring en;
	en = "Reply-To: ";
	en += m_NameAddr.Encode();
	en += m_Params.Encode();
	return en;
}
mystring CSIPReplyTo::EncodeNoName()
{
	mystring en;
	en = m_NameAddr.Encode();
	en += m_Params.Encode();
	return en;
}
CSIPReplyTo& CSIPReplyTo::operator=(const CSIPReplyTo& rhs)
{   
	m_NameAddr = rhs.m_NameAddr;
	m_Params = rhs.m_Params;
	return *this;
}
bool CSIPReplyTo::operator==(const CSIPReplyTo& other) const
{   
   if(m_NameAddr != other.m_NameAddr)
	   return false;
   
   return true;
}

bool CSIPReplyTo::operator!=(const CSIPReplyTo& other) const
{
   return !(*this == other);
}


CSIPRetryAfter::CSIPRetryAfter()
{
	Clear();
}

CSIPRetryAfter::CSIPRetryAfter(const CSIPRetryAfter &e)
{
	*this = e;
}
CSIPRetryAfter::~CSIPRetryAfter()
{
	Clear();
}
int CSIPRetryAfter::Parse(const char *pbody,int len)
{
	const char *p = pbody;
	int c = 0,c1;
	int lpc = 0;
	mystring delta;
	Clear();
	while(*p != SP)
	{
		if(*p == HTAB || *p == CR || *p == LF || *p == SEMI)
			break;

		delta += *p;
		p++;c++;
		if(c >= len)
			return -1;
	}
	m_nDelta = atoi(delta.c_str());
	//find comment
	SKIPLWS(p,len,c,c1);
	if(*p == LPAREN)
	{//comment = LPAREN *(ctext / quoted-pair / comment) RPAREN
		p++;c++;		
		SKIPLWS(p,len,c,c1);
		while(1)
		{
			if(*p == RPAREN && lpc == 0)
				break;
			if(*p == CR || *p == LF)
				continue;
			if(*p == LPAREN)
				lpc++;
			else if(*p == RPAREN)
				lpc--;
			m_strComment += *p;
			p++;c++;
			if(c >= len)
				return -1;			
		}
		p++;c++;
		SKIPLWS(p,len,c,c1);		
	}
	while(*p == SEMI)
	{
		p++;c++;
		SKIPLWS(p,len,c,c1);
		c1 = m_Params.ParseVIAParams(p,len - c);
		if(c1 == -1)
			return -1;
		p+=c1;
		c+=c1;
		SKIPLWS(p,len,c,c1);
	}
	return c;	
}
mystring CSIPRetryAfter::Encode()
{
	char buf[32];
	mystring en;
	en = "Retry-After: ";
	sprintf(buf,"%d",m_nDelta);
	en += buf;
	if(m_strComment.empty() == false)
		en += " " + m_strComment;
	en += m_Params.Encode();
	return en;
}

mystring CSIPRetryAfter::EncodeNoName()
{
	char buf[32];
	mystring en;	
	sprintf(buf,"%d",m_nDelta);
	en += buf;
	if(m_strComment.empty() == false)
		en += " " + m_strComment;
	en += m_Params.Encode();
	return en;
}

CSIPRetryAfter& CSIPRetryAfter::operator=(const CSIPRetryAfter& rhs)
{
	Clear();
	this->m_strComment = rhs.m_strComment;
	this->m_nDelta = rhs.m_nDelta;
	this->m_Params = rhs.m_Params;
	return *this;
}
bool CSIPRetryAfter::operator==(const CSIPRetryAfter& other) const
{
	if(m_nDelta != other.m_nDelta)
		return false;
	if(m_strComment != other.m_strComment)
		return false;
	if(m_Params != other.m_Params)
		return false;
	return true;
}
bool CSIPRetryAfter::operator!=(const CSIPRetryAfter& other) const
{
	return !(*this == other);
}
void CSIPRetryAfter::Clear()
{	
	m_strComment.erase();	
	m_nDelta = 0;
	m_Params.Clear();
}



CSIPSubject::CSIPSubject()
{
	
}

CSIPSubject::CSIPSubject(const CSIPSubject &e)
{
	*this = e;
}
CSIPSubject::~CSIPSubject()
{
	Clear();
}
int CSIPSubject::Parse(const char *pbody,int len)
{
	const char *p = pbody;
	int c = 0,c1,c2;	
	Clear();
	SKIPLWS(p,len,c,c1);
	while(*p)
	{
		if(*p == CR || *p == LF)
			break;
		m_strSubject += *p;
		p++;c++;
		c2 = c;
		SKIPLWS(p,len,c,c1);
		if(c > c2)
			m_strSubject += " ";
		if(c >= len)
			return -1;
	}
	return c;	
}
mystring CSIPSubject::Encode()
{
	mystring en;
	en = "Subject: ";
	en += m_strSubject;	
	return en;
}

mystring CSIPSubject::EncodeNoName()
{
	mystring en;
	en = m_strSubject;
	return en;
}

CSIPSubject& CSIPSubject::operator=(const CSIPSubject& rhs)
{
	Clear();
	this->m_strSubject = rhs.m_strSubject;
	return *this;
}
bool CSIPSubject::operator==(const CSIPSubject& other) const
{
	if(m_strSubject != other.m_strSubject)
		return false;	
	return true;
}
bool CSIPSubject::operator!=(const CSIPSubject& other) const
{
	return !(*this == other);
}
void CSIPSubject::Clear()
{	
	m_strSubject.erase();	
}



CSIPTimestamp::CSIPTimestamp()
{
	Clear();	
}

CSIPTimestamp::CSIPTimestamp(const CSIPTimestamp &e)
{
	*this = e;
}
CSIPTimestamp::~CSIPTimestamp()
{
	Clear();
}
int CSIPTimestamp::Parse(const char *pbody,int len)
{
	const char *p = pbody;
	int c = 0,c1;	
	Clear();
	while(*p != SP)
	{
		if(*p == CR || *p == LF)
			break;
		if(isDIGIT(*p) || *p == '.')
			m_strTimestamp += *p;
		else
			break;
		p++;c++;		
		if(c >= len)
			return -1;
	}
	SKIPLWS(p,len,c,c1);
	while(*p)
	{
		if(*p == CR || *p == LF)
			break;
		if(isDIGIT(*p) || *p == '.')
			m_strDelay += *p;
		else
			break;
		p++;c++;		
		if(c >= len)
			return -1;
	}
	return c;	
}
mystring CSIPTimestamp::Encode()
{
	mystring en;
	en = "Timestamp: ";
	en += m_strTimestamp;
	if(m_strDelay.empty() == false)
		en += " " + m_strDelay;
	return en;
}

mystring CSIPTimestamp::EncodeNoName()
{
	mystring en;
	en = m_strTimestamp;
	if(m_strDelay.empty() == false)
		en += " " + m_strDelay;
	return en;
}

CSIPTimestamp& CSIPTimestamp::operator=(const CSIPTimestamp& rhs)
{
	Clear();
	this->m_strTimestamp = rhs.m_strTimestamp;
	this->m_strDelay = rhs.m_strDelay;
	return *this;
}
bool CSIPTimestamp::operator==(const CSIPTimestamp& other) const
{
	if(m_strTimestamp != other.m_strTimestamp)
		return false;
	if(m_strDelay != other.m_strDelay)
		return false;
	return true;
}
bool CSIPTimestamp::operator!=(const CSIPTimestamp& other) const
{
	return !(*this == other);
}
void CSIPTimestamp::Clear()
{	
	m_strTimestamp.erase();	
	m_strDelay.erase();
}


CSIPWarning::CSIPWarning()
{
	Clear();
}

CSIPWarning::CSIPWarning(const CSIPWarning &e)
{
	*this = e;
}
CSIPWarning::~CSIPWarning()
{
	Clear();
}
int CSIPWarning::Parse(const char *pbody,int len)
{//Warning=warn-code SP warn-agent SP warn-text
	const char *p = pbody;
	int c = 0,c1;	
	Clear();
	mystring code;
	while(*p != SP)
	{
		if(*p == CR || *p == LF)
			break;
		if(isDIGIT(*p))
			code += *p;
		else
			break;
		p++;c++;		
		if(c >= len)
			return -1;
	}
	m_nWarnCode = atoi(code.c_str());
	if(*p == SP)
	{//warn-agent
		p++;c++;
		while(*p != SP)
		{
			if(*p == HTAB || *p == CR || *p == LF)
				break;
			m_strWarnAgent += *p;
			p++;c++;
		}
	}
	if(*p == SP)
	{//warn-text
		p++;c++;
		SKIPLWS(p,len,c,c1);
		if(*p == DQUOTE)
		{
			p++;c++;
			while(*p != DQUOTE)
			{
				m_strWarnText += *p;
				p++;c++;
				if(c >= len)
					return -1;
			}
			*p++;c++;
			SKIPLWS(p,len,c,c1);
		}
	}
	return c;	
}
mystring CSIPWarning::Encode()
{
	char buf[32];
	mystring en;
	en = "Warning: ";
	sprintf(buf,"%03d",m_nWarnCode);
	en += buf;
	en += " ";
	en += m_strWarnAgent;
	en += " ";
	en += "\"" + m_strWarnText + "\"";
	
	return en;
}

mystring CSIPWarning::EncodeNoName()
{
	char buf[32];
	mystring en;	
	sprintf(buf,"%03d",m_nWarnCode);
	en += buf;
	en += " ";
	en += m_strWarnAgent;
	en += " ";
	en += "\"" + m_strWarnText + "\"";	
	return en;
}

CSIPWarning& CSIPWarning::operator=(const CSIPWarning& rhs)
{
	Clear();
	this->m_strWarnAgent = rhs.m_strWarnAgent;
	this->m_strWarnText = rhs.m_strWarnText;
	this->m_nWarnCode = rhs.m_nWarnCode;
	return *this;
}
bool CSIPWarning::operator==(const CSIPWarning& other) const
{
	if(this->m_nWarnCode != other.m_nWarnCode)
		return false;
	if(this->m_strWarnAgent != other.m_strWarnAgent)
		return false;
	if(this->m_strWarnText != other.m_strWarnText)
		return false;
	
	return true;
}
bool CSIPWarning::operator!=(const CSIPWarning& other) const
{
	return !(*this == other);
}
void CSIPWarning::Clear()
{	
	this->m_strWarnAgent.erase();
	this->m_strWarnText.erase();
	this->m_nWarnCode = 0;	
}


CSIPUnsupported::CSIPUnsupported()
{
	m_eType = Unsupported;
}

CSIPUnsupported::CSIPUnsupported(const CSIPUnsupported &e)
{
	*this = e;
}
CSIPUnsupported::~CSIPUnsupported()
{
	Clear();
}
int CSIPUnsupported::Parse(const char *pbody,int len)
{
	m_strOptionTag.erase();
	const char *p = pbody;
	int c = 0;
	mystring optiontag;
	while(*p != COMMA)
	{
		if(*p == SP || *p == HTAB || *p == CR || *p == LF)
			break;
		for(int i=0;i<sizeof(g_Reserved);i++)
		{
			if(*p == g_Reserved[i])
				return -1;
		}
		m_strOptionTag += *p;
		p++;
		c++;
		if(c >= len)
			return c;	
	}
	return c;
}
mystring CSIPUnsupported::Encode()
{
	mystring en;
	en = "Unsupported: ";
	en += m_strOptionTag;
	return en;
}
mystring CSIPUnsupported::EncodeNoName()
{
	mystring en;	
	en = m_strOptionTag;
	return en;
}

CSIPUnsupported& CSIPUnsupported::operator=(const CSIPUnsupported& rhs)
{
	this->m_strOptionTag = rhs.m_strOptionTag;
	return *this;
}
bool CSIPUnsupported::operator==(const CSIPUnsupported& other) const
{
	return this->m_strOptionTag == other.m_strOptionTag; 
}
bool CSIPUnsupported::operator!=(const CSIPUnsupported& other) const
{
	return !(*this == other);
}
void CSIPUnsupported::Clear()
{
	m_strOptionTag.erase();
}

CSIPServer::CSIPServer()
{
	
}

CSIPServer::CSIPServer(const CSIPServer &e)
{
	*this = e;
}
CSIPServer::~CSIPServer()
{
	Clear();
}
int CSIPServer::Parse(const char *pbody,int len)
{
	const char *p = pbody;
	int c1 ,c = 0;	
	Clear();
	int lpc = 0;
	struct ServerVal sv;	
	do{
		sv.val.erase();
		SKIPLWS(p,len,c,c1);
		if(*p == LPAREN)
		{//comment = LPAREN *(ctext / quoted-pair / comment) RPAREN
			p++;c++;
			sv.comment = true;
			SKIPLWS(p,len,c,c1);
			while(1)
			{
				if(*p == RPAREN && lpc == 0)
					break;
				if(*p == CR || *p == LF)
					continue;
				if(*p == LPAREN)
					lpc++;
				else if(*p == RPAREN)
					lpc--;
				sv.val += *p;
				p++;c++;
				if(c >= len)
					return -1;
			}
			p++;c++;
			SKIPLWS(p,len,c,c1);
		}
		else
		{//product
			sv.comment = false;
			while(*p != COMMA)
			{
				//if(*p == SP || *p == HTAB || *p == CR || *p == LF)
				//	break;
				if(istoken(*p) == false && *p != SLASH)
					break;
				sv.val += *p;
				p++;
				c++;
				if(c >= len)
					break;
			}
		}
		m_ServerValList.push_back(sv);
		SKIPLWS(p,len,c,c1);
		if(*p == CR || *p == LF)
			break;
	}while(1);
	return c;	
}
mystring CSIPServer::Encode()
{
	mystring en;
	en = "Server:";
	list<struct ServerVal>::iterator it;
	for(it = m_ServerValList.begin(); it != m_ServerValList.end();it++)
	{
		if(it->comment)
			en += " (" + it->val + ")";
		else
			en += " " + it->val;	
	}
	return en;
}

mystring CSIPServer::EncodeNoName()
{
	mystring en;
	list<struct ServerVal>::iterator it;
	for(it = m_ServerValList.begin(); it != m_ServerValList.end();it++)
	{
		if(it->comment)
			en += " (" + it->val + ")";
		else
			en += " " + it->val;	
	}
	return en;
}

CSIPServer& CSIPServer::operator=(const CSIPServer& rhs)
{
	Clear();
	list<struct ServerVal>::const_iterator it;
	for(it = rhs.m_ServerValList.begin(); it != rhs.m_ServerValList.end();it++)
	{
		m_ServerValList.push_back(*it);
	}
	return *this;
}
bool CSIPServer::operator==(const CSIPServer& other) const
{		
	if(m_ServerValList.size() != other.m_ServerValList.size())
		return false;
	/*
	for(it = rhs.m_ServerValList.begin(); it != rhs.m_ServerValList.end();it++)
	{
		m_ServerValList.push_back(*it);
	}
	*/
	return false;
	return true;
}
bool CSIPServer::operator!=(const CSIPServer& other) const
{
	return !(*this == other);
}
void CSIPServer::Clear()
{	
	while(m_ServerValList.empty() == false)
	{
		m_ServerValList.pop_front();
	}	
}

CSIPPriority::CSIPPriority()
{
	
}

CSIPPriority::CSIPPriority(const CSIPPriority &e)
{
	*this = e;
}
CSIPPriority::~CSIPPriority()
{
	Clear();
}
int CSIPPriority::Parse(const char *pbody,int len)
{
	const char *p = pbody;
	int c = 0,c1 = 0;	
	Clear();
	SKIPLWS(p,len,c,c1);
	while(1)
	{
		if(istoken(*p))
			m_strPriority += *p;
		else
			break;
		p++;c++;
		if(c >= len)
			break;
	}
	return c;	
}
mystring CSIPPriority::Encode()
{
	mystring en;
	en = "Priority: ";
	en += m_strPriority;
	return en;
}

mystring CSIPPriority::EncodeNoName()
{
	mystring en;
	en = m_strPriority;
	return en;
}

CSIPPriority& CSIPPriority::operator=(const CSIPPriority& rhs)
{
	Clear();
	this->m_strPriority = rhs.m_strPriority;
	return *this;
}
bool CSIPPriority::operator==(const CSIPPriority& other) const
{	
	if(m_strPriority != other.m_strPriority)
		return false;

	return true;
}
bool CSIPPriority::operator!=(const CSIPPriority& other) const
{
	return !(*this == other);
}
void CSIPPriority::Clear()
{	
	m_strPriority.erase();
}



CSIPFileName::CSIPFileName()
{
	
}

CSIPFileName::CSIPFileName(const CSIPFileName &e)
{
	*this = e;
}
CSIPFileName::~CSIPFileName()
{
	Clear();
}
int CSIPFileName::Parse(const char *pbody,int len)
{//FileName:filename
	const char *p = pbody;
	int c = 0,c1;	
	mystring str;
	Clear();	
	SKIPLWS(p,len,c,c1);
	while(*p != SP)
	{
		if(*p == CR || *p == LF)
			break;
		m_strFileName+= *p;
		p++;c++;
		if(c >= len)
			return -1;
	}	
	return c;	
}
mystring CSIPFileName::Encode()
{
	mystring en;
	en = "FileName: ";
	en += m_strFileName;	
	return en;
}

mystring CSIPFileName::EncodeNoName()
{
	mystring en;
	en = m_strFileName;
	return en;
}

CSIPFileName& CSIPFileName::operator=(const CSIPFileName& rhs)
{
	Clear();
	this->m_strFileName= rhs.m_strFileName;	
	return *this;
}
bool CSIPFileName::operator==(const CSIPFileName& other) const
{	
	if(this->m_strFileName == other.m_strFileName)		
		return true;
	return false;
}
bool CSIPFileName::operator!=(const CSIPFileName& other) const
{
	return !(*this == other);
}
void CSIPFileName::Clear()
{	
	this->m_strFileName.erase();	
}


mystring CSIPScale::Encode()
{
	char buf[24];
	mystring en;
	en = "Scale: ";
	sprintf(buf,"%f ",m_fScale);
	en += buf;
	return en;
}
mystring CSIPScale::EncodeNoName()
{
	char buf[24];
	mystring en;

	sprintf(buf,"%f ",m_fScale);
	en = buf;
	return en;
}

int CSIPScale::Parse(const char *pbody,int len)
{//CSeq = "CSeq" HCOLON 1*DIGIT LWS Method
	const char *p = pbody;
	int c = 0;
	m_fScale = 0.0;
	mystring seq;
	while(*p != SP && *p != HTAB && *p != CR && *p != LF)
	{
		seq += *p;
		p++;
		c++;
		if(c >= len)
			return -1;
	}	
	m_fScale = atof(seq.c_str());	
	return c;
}
CSIPScale& CSIPScale::operator=(const CSIPScale& rhs)
{   
	if (this != &rhs)
	{  
		m_fScale = rhs.m_fScale;
	}
	return *this;
}
bool CSIPScale::operator==(const CSIPScale& other) const
{
   if (m_fScale != other.m_fScale)    
   {
        return true;      
   }
   return true;
}

bool CSIPScale::operator!=(const CSIPScale& other) const
{
   return !(*this == other);
}

bool CSIPScale::operator<(const CSIPScale& other) const
{	
	if (m_fScale < other.m_fScale)
	{
		return true;
	}
	return false;
}




mystring CSIPSeek::Encode()
{
	char buf[24];
	mystring en;
	en = "Seek: ";
	sprintf(buf,"%d ",m_nPos);
	en += buf;
	return en;
}
mystring CSIPSeek::EncodeNoName()
{
	char buf[24];
	mystring en;

	sprintf(buf,"%d ",m_nPos);
	en = buf;
	return en;
}

int CSIPSeek::Parse(const char *pbody,int len)
{//CSeq = "CSeq" HCOLON 1*DIGIT LWS Method
	const char *p = pbody;
	int c = 0;
	m_nPos = 0;
	mystring seq;
	while(*p != SP && *p != HTAB && *p != CR && *p != LF)
	{
		seq += *p;
		p++;
		c++;
		if(c >= len)
			return -1;
	}	
	m_nPos = atoi(seq.c_str());	
	return c;
}
CSIPSeek& CSIPSeek::operator=(const CSIPSeek& rhs)
{   
	if (this != &rhs)
	{  
		m_nPos = rhs.m_nPos;
	}
	return *this;
}
bool CSIPSeek::operator==(const CSIPSeek& other) const
{
   if (m_nPos != other.m_nPos)    
   {
        return true;      
   }
   return true;
}

bool CSIPSeek::operator!=(const CSIPSeek& other) const
{
   return !(*this == other);
}

bool CSIPSeek::operator<(const CSIPSeek& other) const
{	
	if (m_nPos < other.m_nPos)
	{
		return true;
	}
	return false;
}

